Skip to content

Commit 4c46705

Browse files
tvandortclaude
andcommitted
ENG-3275: Populate client_id at write time in EventAuditService and AttachmentService
EventAuditService.create_event_audit() gains an explicit client_id kwarg and falls back to get_client_id() from request context, mirroring the existing user_id / get_user_id() pattern. AttachmentService.create_and_upload() injects client_id from request context into the data dict if the caller hasn't already set it, so API client uploads are attributed without changing every call site. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0e65f30 commit 4c46705

File tree

2 files changed

+12
-2
lines changed

2 files changed

+12
-2
lines changed

src/fides/service/attachment_service.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from loguru import logger
1111
from sqlalchemy.orm import Session
1212

13+
from fides.api.request_context import get_client_id
1314
from fides.api.models.attachment import (
1415
Attachment,
1516
AttachmentReference,
@@ -209,6 +210,11 @@ def create_and_upload(
209210
"""
210211
db = self._require_db()
211212

213+
# Populate client_id from request context if not already set by the caller.
214+
# This covers API client actors whose user_id is None.
215+
if "client_id" not in data:
216+
data = {**data, "client_id": get_client_id()}
217+
212218
# Create the attachment record using internal _create_record to avoid
213219
# triggering the deprecation warning on the public create() method
214220
attachment = Attachment._create_record(db=db, data=data, check_name=check_name)

src/fides/service/event_audit_service.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from sqlalchemy.orm import Session
77

88
from fides.api.models.event_audit import EventAudit, EventAuditStatus, EventAuditType
9-
from fides.api.request_context import get_user_id
9+
from fides.api.request_context import get_client_id, get_user_id
1010

1111

1212
class EventAuditService:
@@ -21,18 +21,22 @@ def create_event_audit(
2121
status: EventAuditStatus,
2222
*,
2323
user_id: Optional[str] = None,
24+
client_id: Optional[str] = None,
2425
resource_type: Optional[str] = None,
2526
resource_identifier: Optional[str] = None,
2627
description: Optional[str] = None,
2728
event_details: Optional[Dict[str, Any]] = None,
2829
) -> EventAudit:
2930
"""Create a new audit event record."""
3031

31-
# Uses the passed in user_id or falls back to the authenticated user via get_user_id()
32+
# Prefer explicit args, then fall back to request context.
33+
# user_id and client_id are mutually exclusive: a request is attributed
34+
# to a human user OR an API client, never both.
3235
data = {
3336
"event_type": event_type,
3437
"status": status,
3538
"user_id": user_id or get_user_id(),
39+
"client_id": client_id or get_client_id(),
3640
"resource_type": resource_type,
3741
"resource_identifier": resource_identifier,
3842
"description": description,

0 commit comments

Comments
 (0)