Documentation

Audit & compliance.

Last updated

Audit log

What it is. A complete, tamper-evident record of everything that happens — logins, query submissions and decisions, datasource changes, channel edits. It's your answer to "who did what, when" for security reviews and compliance. Records are append-only and cryptographically chained, so a deleted or altered entry is detectable after the fact (query result data is never stored).

What makes the AccessFlow audit log tamper-evident?

Every row is append-only and carries an HMAC-SHA256 hash chained to the row before it, so altering or deleting any entry breaks the chain and is detectable. The database role the application uses has no UPDATE or DELETE privilege on the table — a separate writer role only inserts.

Configure it. Nothing to switch on — it captures automatically. Review it at /admin/audit-log:

Audit log admin page with action and resource filters, an actor / resource ID search, an Export CSV button, a Verify chain button, and a chronological list of recent USER_LOGIN events with actor avatars and IP addresses.
/admin/audit-log — filter, paginate, verify the HMAC chain, and export to CSV.
  1. Filter and search. Narrow by action, resource type, actor user id, or resource id; an optional start/end date pair scopes the window.
  2. Verify chain. The Verify chain button re-walks every row's HMAC link in order and surfaces the first mismatch — useful as a recurring auditor check.
  3. Export CSV. Streams the current filter as RFC 4180 CSV with the same columns shown in the UI. Long-running exports respect the same query budget as the table view (use date filters to keep them bounded).

Tune it. The chain-signing key defaults to a per-deployment value derived from ENCRYPTION_KEY; set AUDIT_HMAC_KEY (hex, ≥ 32 bytes) explicitly when you want to manage or rotate it yourself. Inserts run through a dedicated AUDIT_DB_USER / AUDIT_DB_PASSWORD role that has no UPDATE / DELETE rights on the log.

Audit sinks (SIEM & WORM streaming)

What it is. External audit sinks stream the tamper-evident audit log to the systems your SOC already watches — a SIEM, a syslog collector, your own HTTPS endpoint — and archive it to write-once (WORM) object storage. Delivery is at-least-once off a durable per-sink cursor: a slow or dead destination never blocks audit writes, and each sink retries forever with backoff, so nothing is lost while a receiver is down (receivers de-duplicate on the immutable event id). Every streamed event carries its hash-chain links, so an exported window can be verified independently of the database.

Configure it. Manage sinks at /admin/audit-sinks (requires the AUDIT_SINK_MANAGE permission; admins hold it). Pick one of four types — secret fields are write-only: encrypted at rest and shown masked as ******** afterwards:

  • Splunk HECurl (the full HTTP Event Collector endpoint) and token (masked); optional index and source.
  • Syslog / CEFhost, port, and protocol (TCP or TLS; TLS validates against the system truststore — there is deliberately no skip-verify option). Events arrive as RFC 5424 syslog frames carrying CEF.
  • Signed HTTPS batchesurl and secret (masked). Batches are JSON arrays signed with the same X-AccessFlow-Signature HMAC-SHA256 contract as webhook notifications.
  • S3 Object Lock (WORM)bucket, region, access_key_id, secret_access_key (masked), and retention_days; optional prefix, custom S3-compatible endpoint, retention_mode (COMPLIANCE, the immutable default, or GOVERNANCE), and segment_max_age. Audit rows are written as periodic JSONL segments under an Object Lock retention, each with a sibling .sig digital signature you can verify offline against the published signing certificate.

The list shows per-sink delivery health — cursor position, last success, last error, consecutive failures, next retry, and how many events the sink is behind — and a Test button that synchronously pushes one synthetic event through the sink (for S3 it uploads a small unlocked test object, so trying a sink never creates immutable data).

Tune it. ACCESSFLOW_AUDIT_SINKS_DRAIN_INTERVAL (streaming cadence, default PT30S), ACCESSFLOW_AUDIT_SINKS_BATCH_SIZE (rows per delivery, default 500), and ACCESSFLOW_AUDIT_SINKS_MAX_BATCHES_PER_TICK (per-sink catch-up cap per tick, default 5).

S3 bucket prerequisite. The bucket must be created with versioning and Object Lock enabled (aws s3api create-bucket --object-lock-enabled-for-bucket) — Object Lock cannot be enabled on an existing plain bucket — and the IAM principal needs s3:PutObject and s3:PutObjectRetention. COMPLIANCE mode is immutable for everyone until the retention expires; GOVERNANCE allows privileged override.

Compliance reports & signed exports

What it is. Ready-made compliance reporting with audit-grade exports. Two pre-built reports answer common auditor questions over a chosen period: classified-data access (which executed queries touched PII / PCI / PHI / GDPR / FINANCIAL / SENSITIVE data, joined to your data-classification tags) and a regulatory audit trail of DDL / DELETE operations with the approvers' names. Use it to hand a regulator or internal auditor evidence they can verify themselves.

Configure it. Build and export reports from the compliance dashboard at /admin/auditor — open to the read-only AUDITOR role and to admins. Each report exports as a digitally signed PDF or CSV that an auditor can verify offline against the public key at /api/v1/admin/compliance/signing-certificate; every export is itself recorded in the audit log with its content hash, so it's tamper-evident end to end.

Tune it. ACCESSFLOW_COMPLIANCE_MAX_REPORT_PERIOD (largest window, default P366D) and ACCESSFLOW_COMPLIANCE_MAX_ROWS (row cap before a report is marked truncated, default 50000). Signing reuses JWT_PRIVATE_KEY — no extra secret required.

The read-only AccessFlow Auditor dashboard with the compliance report builder for classified-data-access and regulatory audit-trail reports over a chosen period.
/admin/auditor — the read-only Auditor role builds and signs compliance reports over the immutable query snapshots.

Data lifecycle & right-to-erasure

Admin. Define retention/erasure rules at /admin/lifecycle/policies — per datasource, target a table / column set / classification tag with a retention window (ISO-8601, e.g. P30D or P7Y) plus arbitrary conditions (a structured, parameter-bound predicate builder and a JSqlParser-validated raw-WHERE escape hatch — SQL datasources only) and an action: hard-delete, soft-delete, or pseudonymize (salted SHA-256 / format-preserving / tokenization), with an optional cron schedule. A dry-run preview reports impact without executing. The scan job stages eligible work (honouring the cron); tune it with ACCESSFLOW_LIFECYCLE_POLICY_SCAN_INTERVAL (default PT1H). Staged runs now execute automatically through the proxy — ACCESSFLOW_LIFECYCLE_POLICY_EXECUTION_INTERVAL (default PT5M).

Any user can file a right-to-erasure request at /lifecycle/erasure using the same rich configuration (subject identifier and/or target table + conditions). It flows through AI-assisted scope detection and review-plan-based peer review: any eligible REVIEWER or admin reviews it at /lifecycle/erasure-reviews (per the datasource review plan, multi-stage; the submitter can never approve their own), and stale reviews auto-reject via ACCESSFLOW_LIFECYCLE_REVIEW_TIMEOUT (default PT168H). Approved requests are executed through the proxy — soft-deleted rows vanish from reads, DELETEs become marker updates, aged PII resolves to an irreversible salted hash at read time — with tamper-evident proof-of-deletion audit records and a retention-adherence compliance export. Tune the executor with ACCESSFLOW_LIFECYCLE_ERASURE_EXECUTION_INTERVAL (default PT1M).

Personalized dashboard & weekly digest

The default post-login home (/dashboard) is self-scoped — every user sees only their own data, no admin role required: pending approvals as a reviewer, their recent queries with status/risk trend sparklines, an AI optimization-suggestion backlog they can dismiss or open in the editor, and their own behavioural-anomaly alerts. Widgets are customizable (show/hide, collapse, drag-and-drop reorder) and persist per browser. Users can export the week's summary as a digitally signed PDF/CSV on demand, and opt in to a weekly email digest delivered to their email and any configured chat channels. The digest job is clustered-safe; tune it with ACCESSFLOW_DASHBOARD_WEEKLY_DIGEST_POLL_INTERVAL (how often the job wakes, default P1D) and ACCESSFLOW_DASHBOARD_WEEKLY_DIGEST_PERIOD (minimum gap between digests per user, default P7D).