`Audit event type YML file is not defined for ticket_closed_by_project_bot.` returned when a group or project access token is used to close a Service Desk ticket
### Summary When attempting to close a Service Desk ticket using the [Issues API](https://docs.gitlab.com/api/issues/#update-an-issue), and authenticating with a project or group access token, the user is returned with a 500 error, however the work item closes successfully. Checking Rails logs, you can see the below logged exception. ``` Audit event type YML file is not defined for ticket_closed_by_project_bot. Please read https://docs.gitlab.com/ee/development/audit_event_guide/#how-to-instrument-new-audit-events for adding a new audit event ``` ### Steps to reproduce 1. Create a service desk ticket in a project 2. Attempt to close the service desk issue [using the API](https://docs.gitlab.com/api/issues/#update-an-issue) and authenticating with a project or group access token 3. Notice the issue closes, but the HTTP response is [500](https://http.cat/500) ### Example Project N/A ### What is the current *bug* behavior? An erroneous 500 response is returned, and no audit event is created for the service desk issue being closed. ### What is the expected *correct* behavior? A non-500 response should be returned, and an audit event should be created for the closure. ### Relevant logs and/or screenshots ### Output of checks This bug happens on GitLab.com #### Results of GitLab environment info <details> <summary>Expand for output related to GitLab environment info</summary> <pre> (For installations with omnibus-gitlab package run and paste the output of: `sudo gitlab-rake gitlab:env:info`) (For installations from source run and paste the output of: `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`) </pre> </details> #### Results of GitLab application Check <details> <summary>Expand for output related to the GitLab application check</summary> <pre> (For installations with omnibus-gitlab package run and paste the output of: `sudo gitlab-rake gitlab:check SANITIZE=true`) (For installations from source run and paste the output of: `sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`) (we will only investigate if the tests are passing) </pre> </details> ### Possible fixes ### Patch release information for backports If the bug fix needs to be backported in a [patch release](https://handbook.gitlab.com/handbook/engineering/releases/patch-releases) to a version under [the maintenance policy](https://docs.gitlab.com/policy/maintenance/), please follow the steps on the [patch release runbook for GitLab engineers](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/patch/engineers.md). Refer to the [internal "Release Information" dashboard](https://dashboards.gitlab.net/d/delivery-release_info/delivery3a-release-information?orgId=1) for information about the next patch release, including the targeted versions, expected release date, and current status. #### High-severity bug remediation To remediate high-severity issues requiring an [internal release](https://handbook.gitlab.com/handbook/engineering/releases/internal-releases/) for single-tenant SaaS instances, refer to the [internal release process for engineers](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/internal-releases/engineers.md?ref_type=heads). --- ## Root Cause Analysis The audit event name is dynamically generated in `app/services/issues/close_service.rb` (lines 58-60): ```ruby if current_user.project_bot? log_audit_event(issue, current_user, "#{issue.issue_type}_closed_by_project_bot", "Closed #{issue.issue_type.humanize(capitalize: false)} #{issue.title}") end ``` When `issue.issue_type` returns `ticket`, the generated audit event name becomes `ticket_closed_by_project_bot`. However, no corresponding YML definition exists in `ee/config/audit_events/types/`, causing the error. This gap exists because the `ticket` work item type was introduced as part of the Service Desk migration to work items **after** the original audit events were created in GitLab 16.1 (!121485). ### Why "project_bot" in the naming The `_by_project_bot` suffix is a historical artifact. Both project and group access tokens create users with `user_type: project_bot` (defined in `app/models/concerns/has_user_type.rb`). The check `current_user.project_bot?` returns true for both token types, which is why the audit event naming uses `project_bot` even when a group access token is used. --- ## Implementation Plan ### 1. Create audit event type definitions Add the following files in `ee/config/audit_events/types/`: - [ ] `ticket_closed_by_project_bot.yml` - [ ] `ticket_reopened_by_project_bot.yml` - [ ] `ticket_created_by_project_bot.yml` (proactive, for future API support) Each file should follow the existing pattern. Example for `ticket_closed_by_project_bot.yml`: ```yaml --- name: ticket_closed_by_project_bot description: A Service Desk ticket is closed using a project access token introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/592448 introduced_by_mr: <MR URL> feature_category: service_desk milestone: '<current milestone>' saved_to_database: true streamed: true scope: [Project] ``` ### 2. Regenerate audit event documentation - [ ] Run `bundle exec rake gitlab:audit_event_types:compile_docs` to update `doc/user/compliance/audit_event_types.md` ### 3. Add specs Update existing spec files to include ticket-specific test cases: - [ ] `ee/spec/services/ee/issues/close_service_spec.rb` - Add test for closing a ticket with a project bot user - [ ] `ee/spec/services/ee/issues/reopen_service_spec.rb` - Add test for reopening a ticket with a project bot user - [ ] `ee/spec/workers/ee/new_issue_worker_spec.rb` - Add test for ticket creation audit event (proactive) Example spec pattern (based on existing `issue` tests in `ee/spec/services/ee/issues/close_service_spec.rb`): ```ruby context 'when closing a ticket with project bot' do let(:service) { described_class.new(container: project, current_user: project_bot) } let_it_be(:project_bot) { create(:user, :project_bot, email: "bot@example.com") } let_it_be(:ticket_type) { create(:work_item_type, :ticket) } before do project.add_maintainer(project_bot) end include_examples 'audit event logging' do let(:ticket) { create(:issue, title: "My ticket", project: project, author: project_bot, work_item_type: ticket_type) } let(:operation) { service.execute(ticket) } let(:event_type) { 'ticket_closed_by_project_bot' } let(:fail_condition!) { expect(project_bot).to receive(:project_bot?).and_return(false) } let(:attributes) do { author_id: project_bot.id, entity_id: ticket.project.id, entity_type: 'Project', details: { author_name: project_bot.name, event_name: "ticket_closed_by_project_bot", target_id: ticket.id, target_type: 'Issue', target_details: { iid: ticket.iid, id: ticket.id }.to_s, author_class: project_bot.class.name, custom_message: "Closed ticket #{ticket.title}" } } end end end ``` ### 4. Verify the fix - [ ] Manually test closing a Service Desk ticket via API with a project access token - [ ] Manually test closing a Service Desk ticket via API with a group access token - [ ] Verify audit event is recorded in the project's audit events - [ ] Verify no 500 error is returned --- ## Files to Create | File | Purpose | |------|---------| | `ee/config/audit_events/types/ticket_closed_by_project_bot.yml` | Audit event definition for closing tickets | | `ee/config/audit_events/types/ticket_reopened_by_project_bot.yml` | Audit event definition for reopening tickets | | `ee/config/audit_events/types/ticket_created_by_project_bot.yml` | Audit event definition for creating tickets (proactive) | ## Files to Update | File | Change | |------|--------| | `doc/user/compliance/audit_event_types.md` | Auto-generated via rake task | | `ee/spec/services/ee/issues/close_service_spec.rb` | Add ticket-specific audit event test | | `ee/spec/services/ee/issues/reopen_service_spec.rb` | Add ticket-specific audit event test | | `ee/spec/workers/ee/new_issue_worker_spec.rb` | Add ticket-specific audit event test (proactive) |
issue