SEC-007 Part C — per-workspace SIEM forwarder configuration.
Stores the admin-configured webhook target (URL, HMAC secret, optional custom headers) the audit-log forwarder uses to push every event to a customer's SIEM. Schema defined by migration 032.
Encryption-at-rest
The hmacSecret column is encrypted via credentialEncryption.js
(AES-256-GCM) before persist and decrypted lazily on read. The
encryption key is the same one used for AI provider keys and TOTP
secrets — derived from JWT_SECRET (or CREDENTIAL_ENCRYPTION_KEY
if explicitly set).
Read API conventions
getDecrypted(workspaceId)— full row withhmacSecretdecrypted. ONLY for the forwarder to dispatch events. NEVER return this to a client.getMasked(workspaceId)— same shape buthmacSecretreplaced with"••••••••<last4>". Use forGET /siem-configadmin responses.
Methods
(static) getDecrypted(workspaceId) → {Object|null}
Return the decrypted config for the forwarder.
SECURITY: the returned object contains the PLAINTEXT hmacSecret.
Callers MUST NOT log it, return it in HTTP responses, or persist it
back to disk. Only the in-process forwarder should ever call this.
Parameters:
| Name | Type | Description |
|---|---|---|
workspaceId |
string |
Returns:
- Type
- Object | null
(static) getMasked(workspaceId) → {Object|null}
Return the masked config for client display (admin Settings panel).
hmacSecret is masked; the raw value is NEVER exposed.
Parameters:
| Name | Type | Description |
|---|---|---|
workspaceId |
string |
Returns:
- Type
- Object | null
(static) remove(workspaceId) → {boolean}
Delete the SIEM config for a workspace. Returns true if a row was removed, false when none existed (idempotent).
Parameters:
| Name | Type | Description |
|---|---|---|
workspaceId |
string |
Returns:
- Type
- boolean
(static) upsert(workspaceId, cfg) → {Object}
Upsert the SIEM config for a workspace. The HMAC secret is encrypted before persist so even a DB-dump leak doesn't yield usable secrets.
hmacSecret semantics
- Insert path (no existing row):
hmacSecretis required — the caller MUST pass a non-empty string. Callers should validate length upstream (PUT route enforces ≥ 32 chars per NIST SP 800-107). - Update path (row exists):
hmacSecretis OPTIONAL. Pass it to rotate the secret; omit (undefined) or pass the empty string to keep the existing encrypted secret unchanged. Admins editing just thetargetUrl/enabled/headersshould not be forced to re-enter the masked secret they can't see.
Parameters:
| Name | Type | Description | |||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
workspaceId |
string | ||||||||||||||||||||||||||
cfg |
Object |
Properties
|
Throws:
-
When inserting a new row and
hmacSecretis missing/empty. - Type
- Error
Returns:
The persisted row (without the plaintext secret).
- Type
- Object