Skip to content

Audit Log

Every state-changing action in Vygl produces an audit-log entry. Triage decisions, member invites, role changes, integration setup, custom rule edits, scan submissions, API key creation — all logged with the actor, timestamp, target resource, HTTP context, and a structured event payload. Useful for compliance reviews, post-incident reconstruction, and detecting abuse.

Each entry includes:

FieldExample
actionfinding.status_change, member.invite, integration.create
actor (user or API key)The user ID or key prefix
auth_typejwt, api_key, mcp
resource_type / resource_idThe thing being mutated (finding, member, rule, …)
org_idAlways present — every entry is org-scoped
ip_addressThe request IP
user_agentThe client that made the request
http_method / http_path / status_codeFull request context
detailsStructured JSON specific to the action (old value, new value, reason, …)
created_atUTC timestamp

Vygl ships with 200+ distinct action types covering auth, organizations, members, projects, scans, findings, rules, integrations, memory, and admin actions.

The audit log is admin-only. Filters:

  • Action categoryauth.*, finding.*, scan.*, project.*, org.*, rule.*, integration.*, memory.*, admin.*
  • Actor — by user ID or API key prefix
  • Date range
  • Path / method — useful for tracking specific endpoints
  • Status code — 4xx / 5xx for failure analysis

For org admins, the audit log surfaces in Settings → Audit Log. Superadmins have access to a broader view across all orgs.

Audit entries are append-only — there’s no API to edit or delete them. This is intentional: the audit log’s value as a compliance artifact comes from immutability. To remove an entry, ops would need direct database access plus a paper trail.

Who marked these findings false-positive?

Filter action = finding.status_change, group by actor, look for spikes. False-positive abuse — a user mass-marking findings FP to silence them — is trivially detectable from this query.

Did this API key do anything unexpected?

Filter by the key’s prefix in actor. The full request history of a key is reconstructable from the log.

Who set up the Slack integration?

Filter action = integration.create, details.provider = slack.

Audit entries are retained indefinitely — there’s no automated pruning. Retention is implemented as “the row is never deleted”, not as a scheduled archive policy.