The argument was technically optional for years, and omitting it means no authorisation at all — which is how an endpoint meant for the admin ends up readable by anyone.
register_rest_route( 'turkerdev/v1', '/reports/(?P<id>d+)', array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'turkerdev_get_report',
'permission_callback' => function ( WP_REST_Request $request ) {
return current_user_can( 'read_report', (int) $request['id'] );
},
'args' => array(
'id' => array(
'required' => true,
'validate_callback' => 'is_numeric',
'sanitize_callback' => 'absint',
),
),
) );
Checking a capability against the specific object rather than a blanket manage_options is what makes an endpoint usable by a non-administrator without opening everything. The args block is the half most often skipped: validation runs before the callback, so the callback can assume well-formed input. WordPress 5.5 started emitting a doing-it-wrong notice for a missing callback, which is what finally made this visible.