Expose humanAuthor on AiAuditEvent GraphQL type

What does this MR do and why?

Adds a humanAuthor field of type UserType to Types::AuditEvents::AiAuditEventType, resolved from details['human_author_id'] stored in the event. Updates both session audit event GraphQL queries to fetch humanAuthor, and renders <Service account> on behalf of <Human> in the Agent artifacts UI.

Under composite identity, IngestAuditEventsService sets author_id to the service account and records the human in details as human_author_id, human_author_name, and human_author_username. To render the "on behalf of" attribution with a link to the human's profile, the frontend needs a webPath and avatarUrl — which details does not carry.

Why resolve from human_author_id rather than alternatives:

  • Constructing /{username} in the frontend is fragile (breaks under relative URL root, produces dead links after renames or for deleted users)
  • Storing web_path/avatar_url in details at ingest only works for new events, leaving existing compliance data broken

Resolving from human_author_id works retroactively for all existing events, stays correct after renames, and requires no storage or streaming changes.

Performance: Both author and human_author route through the same private batch_load_user method, which uses a single BatchLoader::GraphQL block. batch-loader groups pending loads by block source location, so sharing the block means one User.id_in(...) query per page regardless of how many events are on the page.

References

Screenshots or screen recordings

Screenshot_2026-08-11_at_10.57.06_AM

How to set up and validate locally

  1. Create a composite-identity session (service account acting on behalf of a human user)
  2. Navigate to GraphQL explorer
  3. Use the following query to verify the human user is returned in the response
query getGroupSessionAuditEvents(
  $groupFullPath: ID!
  $workflowId: AiDuoWorkflowsWorkflowID!
  $after: String
  $before: String
  $first: Int
  $last: Int
) {
  group(fullPath: $groupFullPath) {
    id
    duoWorkflowSessionArtifacts(workflowId: $workflowId) {
      nodes {
        id
        auditEvents(after: $after, before: $before, first: $first, last: $last) {
          nodes {
            id
            author {
              id
              name
              username
              avatarUrl
              webPath
            }
            humanAuthor {
              id
              name
              username
              avatarUrl
              webPath
            }
          }
          pageInfo {
            hasNextPage
            hasPreviousPage
            startCursor
            endCursor
          }
        }
      }
    }
  }
}

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Scott Hampton

Merge request reports

Loading
Loading