Audit export to SIEM

Task 6743 · Done · Coder · created · updated

Epic 6714. Child C7 of the architecture. Covers PRD ask F3 and its S.1 gate. `depends_on` the retention child only to serialize schema migrations. ## Original requirement (epic body, verbatim) "Missing features: ... audit export to SIEM ..." Done means: "Every feature above runs." Decision D-F3: one destination type, HTTPS JSON. ## Acceptance criteria (PRD, verbatim) **Environment:** dev = `dev.jaah.ai` (browser face `https://app.dev.jaah.ai`); browser user flows; unit tests required but never sufficient; ON by default on dev; the verifying org is on Enterprise. - **F3.1** An org admin on a plan with the SIEM switch configures an HTTPS destination (URL plus an auth header or HMAC secret, stored as a secret). Every org audit/activity event is delivered as JSON within 5 minutes, at-least-once with retry. A "send test event" button and the last delivery status and error are shown. - **S.1** Each of F1–F8 has its own plan switch, per-org overridable, default OFF. With the switch off, the feature's settings show an upgrade prompt and its APIs return 403 naming the plan feature. - **Quality** Each new setting appears on the page where peers live. Labels follow `docs/standards/ui-copy-standards.md`. Nothing truncated or overflowing. Every refusal names what to do next. A cramped, unlabeled or raw-key UI fails. ## Approach (architecture C7, settled) - Schema: `org_siem_destinations` (org_id unique, url https only, `auth_mode` header|hmac, `header_name`, `secret` sealed via `credential_crypto.seal_secret` with AAD = row id, `cursor_event_id bigint`, `last_attempt_at`, `last_success_at`, `last_status`, `last_error`, `enabled`). - Delivery: system cron `siem-export` (60 s): per destination read `activity_events WHERE org_id=… AND id > cursor ORDER BY id LIMIT 500`, POST a JSON array (id, org_id, created_at, kind, action_type, actor, summary, path, method, status, data), HMAC `X-Jaah-Signature: sha256=…` or the header; 2xx → advance cursor; else record error and retry next cycle (consumers dedupe on `id`). Delivers only while `siem_export_enabled` is on. - Scope: `activity_events` only (not `CommandAudit`). "Send test event" posts one synthetic event without moving the cursor. An outage longer than the org's retention loses those events, shown as an error (R8, accepted). - Gate: `require_switch(..., "siem_export_enabled")`; `PlanUpgradeNotice` when off. Console: Settings › Security › Audit export. - One expand-only migration; re-point `down_revision` at rebase. Credentials & reach: - Console oracles on dev: `jaah/debug/main/operator-login` on `app.dev.jaah.ai` — verified. - F3 SIEM capture: `webhook.site` request capture, no credential — verified — answered 200. Out of scope: Do NOT include `CommandAudit`, syslog or S3 destinations (deferred, D-F3). Do NOT change the operator's S3 security archive (N5). Do NOT touch the marketing site or `docs/compliance/public/` (N2). Never show a stored secret after save. Done means: - F3.1 → verify: on dev, point the export at a request-capture endpoint, create a project and observe the event arrive within 5 minutes (HMAC signature verifiable). Click "Send test event" and observe it arrive. Break the URL and observe the error and retry status in the console; fix it and observe the backlog delivered. - Non-HTTPS URL refused with a message (unit test plus console). - S.1 → verify: on dev, view the audit export settings on a Business org (upgrade prompt; API 403 naming "SIEM export") and on an Enterprise org (available). - Quality → verify: Settings › Security › Audit export at desktop and phone width: readable labels, status/error legible and not truncated, no raw keys.

Outcome

SIEM audit export shipped (PR #5986, lane-merged 1b892842b). Includes the table, the 60 s cron, the API and an Audit export tab beside the IP allowlist. Review blockers were fixed and the local visual check was good. Full gate red only on develop-side tests (draft #7391). Dev oracles deferred. Deploy: dev apply OK; bundle upload stalled, superseded.

Pull request

Artifacts

Activity

  • Draft
  • Ready
  • Runner started
  • Runner ended (done)