Skip to content

fix(logging): register the operation REST filter param#758

Draft
i-anubhav-anand wants to merge 1 commit into
WordPress:developfrom
i-anubhav-anand:fix/log-operation-rest-param
Draft

fix(logging): register the operation REST filter param#758
i-anubhav-anand wants to merge 1 commit into
WordPress:developfrom
i-anubhav-anand:fix/log-operation-rest-param

Conversation

@i-anubhav-anand

@i-anubhav-anand i-anubhav-anand commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

What?

Registers the operation query parameter on the AI Request Log REST endpoint (/ai/v1/logs).

operation is read and applied as a filter server-side and is sent by the Request Log admin UI, but it was the only filter parameter missing from AI_Request_Log_Controller::get_collection_params().

Why?

Because the parameter was unregistered:

  1. It bypassed the REST framework's argument validation. The repository parses it as a comma-separated string:

    // includes/Logging/AI_Request_Log_Repository.php
    $operations = array_filter( array_map( 'trim', explode( ',', $args['operation'] ) ) );

    The admin UI always sends a string (operations.join(',')), but the public endpoint accepts whatever a client sends. A non-string value reaches explode() and raises a fatal:

    GET /ai/v1/logs?operation[]=openai:completions&operation[]=google:generateContent
    → TypeError: explode(): Argument #2 ($string) must be of type string, array given
      at includes/Logging/AI_Request_Log_Repository.php:475   (HTTP 500)
    
  2. It was missing from the REST schema, so API consumers couldn't discover it via schema introspection — unlike every sibling filter (type, status, provider, search, …).

How?

Add operation to get_collection_params() as a string parameter, matching the documented comma-separated contract. WordPress then validates the type before the value reaches the repository (a non-string value is rejected with a 400 instead of fataling), and the parameter is now part of the endpoint schema.

'operation' => array(
    'description' => __( 'Filter by operation. Accepts a single value or a comma-separated list.', 'ai' ),
    'type'        => 'string',
    'default'     => '',
),

This is a one-parameter, surgical change; no behavior changes for the existing (string) filter path.

Use of AI Tools

AI assistance: Yes
Tool(s): AI coding assistant (agentic CLI)
Used for: auditing the REST controller/repository, reproducing the bug, and drafting the fix + tests. All code was written test-first, executed, and reviewed by me; I take responsibility for it.

Testing Instructions

npm run wp-env:test start
npm run test:php -- --filter AI_Request_Log_ControllerTest

Added/extended tests in tests/Integration/Includes/Logging/AI_Request_Log_ControllerTest.php:

  • test_get_collection_params_returns_expected_keys — now also asserts operation is a registered param.
  • test_get_logs_filters_by_operation — the filter returns only matching rows (baseline; passes before and after).
  • test_get_logs_rejects_non_string_operation — an array operation value is handled with a 400 rather than a fatal.

Fail-before / pass-after (source registration reverted, tests kept):

# before:
1) ...::test_get_collection_params_returns_expected_keys
Failed asserting that an array has the key 'operation'.

2) ...::test_get_logs_rejects_non_string_operation
TypeError: explode(): Argument #2 ($string) must be of type string, array given
   at includes/Logging/AI_Request_Log_Repository.php:475

# after:
OK (3 tests, 22 assertions)

Full Logging suite is green (122 tests); full integration suite is green (840 tests, 34 pre-existing skips).

Changelog Entry

Fixed - The AI Request Log REST endpoint now registers its operation filter parameter, so it appears in the REST schema and a non-string value returns a 400 instead of causing a fatal error.

Open WordPress Playground Preview

The /ai/v1/logs endpoint reads and applies an `operation` filter (sent by the Request Log admin UI as a comma-separated string and parsed with explode()), but it was the only filter parameter missing from get_collection_params(). As a result it was absent from the REST schema and bypassed the framework's argument validation, so a non-string value (e.g. operation[]=a&operation[]=b) reached explode() and raised a TypeError, returning a 500.

Register `operation` as a string collection param, matching the documented comma-separated contract. WordPress now validates the type before the value reaches the repository, and the parameter is discoverable in the REST schema like every sibling filter.
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: i-anubhav-anand <anubhav24@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.26%. Comparing base (77f116e) to head (826d996).
⚠️ Report is 58 commits behind head on develop.

Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #758      +/-   ##
=============================================
+ Coverage      74.45%   76.26%   +1.80%     
- Complexity      1740     1765      +25     
=============================================
  Files             85       85              
  Lines           7521     7596      +75     
=============================================
+ Hits            5600     5793     +193     
+ Misses          1921     1803     -118     
Flag Coverage Δ
unit 76.26% <100.00%> (+1.80%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@i-anubhav-anand i-anubhav-anand marked this pull request as draft June 22, 2026 17:51
@jeffpaul jeffpaul added this to the 1.2.0 milestone Jun 26, 2026
@jeffpaul jeffpaul moved this from Triage to In progress in WordPress AI Roadmap Jun 26, 2026
@jeffpaul

Copy link
Copy Markdown
Member

@i-anubhav-anand is this still in progress or can it come out of draft for review?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

2 participants