Security Logs & SIEM
The company security log: what is recorded, how it is protected, and how to feed it into your SIEM.
What is recorded
Account admins get a company-wide security log under Account admin, Security log. Every audited action across the organization lands there:
| Category | Events |
|---|---|
| Authentication | sign-in success and failure, account lockout, password change and reset, 2FA enabled and disabled, sessions revoked |
| Access control | every workspace, base, and board permission change (who, before, after) |
| Account administration | member role changes, removals, joins, organization rename, audit stream changes |
| Data | record created, updated, deleted (with redacted before and after snapshots) |
| Structure | workspace, base, and board deletions |
| API keys | key created and revoked (never the key itself) |
Each entry carries the actor, the resource, before and after snapshots where relevant, the client IP address, and the user agent.
High-risk alerts
Account admins are notified automatically when high-risk activity lands in the log. Alerts arrive in the bell and by email (controllable under notification preferences), and every alerted event carries a High risk badge in the security log.
No spam by design: one incident produces one alert. Repeats of the same event by the same actor within an hour are recorded in the log but not re-notified, and the acting user is never notified about their own action.
Tamper resistance and retention
The log is append-only, enforced at the database itself: an UPDATE on any audit row is rejected by a trigger, and DELETE is blocked except for the optional retention purge, which runs inside a guarded transaction.
Retention is off by default, so history is kept indefinitely. Deployments can set a retention window; expiry then removes whole old rows but can never alter a kept one.
Encrypted field values are redacted in audit snapshots. The log records that a value changed, not the sensitive value itself.
Pull: the export API
For SIEM pollers, Sajel exposes a cursor-paginated export endpoint. It requires an API key with the explicit audit:read scope, owned by an account admin. Wildcard and full-access keys are refused for this resource, so the audit log can only be reached by a key that names it.
Create a scoped key
Go to Settings, API keys, New key, choose Custom, and tick read on the audit row. Limit the key further if you like.
Poll the endpoint
curl -H "x-api-key: sajel_sk_..." "https://your-host/companies/COMPANY_ID/audit/export?eventType=auth.&limit=500"Follow the cursor
The response is { items, nextCursor, hasMore }. Pass nextCursor back as the after parameter to tail the log. Filters: eventType (prefix, e.g. auth.), userId, from, to (ISO timestamps), limit (up to 1000).
Push: audit streams
For real-time forwarding, create an audit stream under Account admin, Security log, SIEM integration. Sajel POSTs each event to your endpoint as JSON:
{ "event": "audit.event", "timestamp": "...", "audit": { "eventType": "auth.login_failed", ... } }Deliveries are signed and retried with exponential backoff (5 attempts). Failed endpoints never affect the action being audited. Streams can subscribe to everything or to a category (auth.*, permission.*, company.*, api_key.*).
Verifying signatures
Every delivery carries two headers: X-Sajel-Signature and X-Sajel-Timestamp. The signature is HMAC-SHA256 over the string timestamp.body using your stream secret (shown once at creation, rotatable any time).
Read the timestamp header and reject stale deliveries
Allow a small window (for example 5 minutes) to block replays.
Recompute the HMAC
HMAC-SHA256(secret, timestamp + "." + rawBody) and compare it to X-Sajel-Signature with a constant-time comparison.
Splunk (HTTP Event Collector via a small relay or generic webhook input), Elastic (custom webhook integration), and Microsoft Sentinel (Logs Ingestion API via an Azure Function) can all consume this shape. For pull-based collectors, point them at the export API instead.