Commit 1962750c5f7 for woocommerce

commit 1962750c5f7feb314a81c65deaf1bf212f4c7407
Author: Néstor Soriano <konamiman@konamiman.com>
Date:   Wed May 20 11:00:57 2026 +0200

    Make GraphQL code accessible externally not internal (#65151)

    * Move GraphQL runtime infrastructure to Api\Infrastructure
    * Move design-time build tooling for GraphQL to bin/api-builder/

diff --git a/.github/workflows/api-staleness.yml b/.github/workflows/api-staleness.yml
index 25752dbbb96..2c1d9775718 100644
--- a/.github/workflows/api-staleness.yml
+++ b/.github/workflows/api-staleness.yml
@@ -5,13 +5,13 @@ on:
         paths:
             - 'plugins/woocommerce/src/Api/**'
             - 'plugins/woocommerce/src/Internal/Api/Autogenerated/**'
-            - 'plugins/woocommerce/src/Internal/Api/DesignTime/**'
+            - 'plugins/woocommerce/bin/api-builder/**'
             - '.github/workflows/api-staleness.yml'
     push:
         paths:
             - 'plugins/woocommerce/src/Api/**'
             - 'plugins/woocommerce/src/Internal/Api/Autogenerated/**'
-            - 'plugins/woocommerce/src/Internal/Api/DesignTime/**'
+            - 'plugins/woocommerce/bin/api-builder/**'
             - '.github/workflows/api-staleness.yml'
         branches:
             - 'trunk'
diff --git a/plugins/woocommerce/.distignore b/plugins/woocommerce/.distignore
index c74f49cc915..b5cf98a1bcb 100644
--- a/plugins/woocommerce/.distignore
+++ b/plugins/woocommerce/.distignore
@@ -48,4 +48,4 @@ webpack.config.js
 phpstan.neon
 phpstan-baseline.neon
 /php-stubs/
-/src/Internal/Api/DesignTime/
+/bin/api-builder/
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/ApiBuilder.php b/plugins/woocommerce/bin/api-builder/ApiBuilder.php
similarity index 99%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/ApiBuilder.php
rename to plugins/woocommerce/bin/api-builder/ApiBuilder.php
index 8aa5abe8237..0d87ef90cd2 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/ApiBuilder.php
+++ b/plugins/woocommerce/bin/api-builder/ApiBuilder.php
@@ -2,7 +2,7 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api\DesignTime\Scripts;
+namespace Automattic\WooCommerce\Api\Infrastructure\DesignTime;

 use Automattic\WooCommerce\Api\Attributes\ArrayOf;
 use Automattic\WooCommerce\Api\Attributes\ConnectionOf;
@@ -32,7 +32,7 @@ use Automattic\WooCommerce\Api\Infrastructure\Principal;
  * core's build pipeline is unaffected.
  */
 class ApiBuilder {
-	private const TEMPLATES_DIR = __DIR__ . '/../Templates';
+	private const TEMPLATES_DIR = __DIR__ . '/code-templates';

 	private string $api_dir;
 	private string $autogenerated_dir;
@@ -72,18 +72,18 @@ class ApiBuilder {
 			);
 		}

-		$this->api_dir                 = $api_dir ?? realpath( __DIR__ . '/../../../../Api' );
-		$this->autogenerated_dir       = $autogenerated_dir ?? realpath( __DIR__ . '/../../Autogenerated' );
+		$this->api_dir                 = $api_dir ?? realpath( __DIR__ . '/../../src/Api' );
+		$this->autogenerated_dir       = $autogenerated_dir ?? realpath( __DIR__ . '/../../src/Internal/Api/Autogenerated' );
 		$this->api_namespace           = $api_namespace ?? 'Automattic\\WooCommerce\\Api';
 		$this->autogenerated_namespace = $autogenerated_namespace ?? 'Automattic\\WooCommerce\\Internal\\Api\\Autogenerated';
-		$this->phpcbf_path             = $phpcbf_path ?? realpath( __DIR__ . '/../../../../..' ) . '/vendor/bin/phpcbf';
+		$this->phpcbf_path             = $phpcbf_path ?? realpath( __DIR__ . '/../..' ) . '/vendor/bin/phpcbf';

 		// Default composer working dir to WooCommerce core's plugin dir when no
 		// override is given, so core's existing invocation keeps working. When
 		// an external caller passes --api-dir they presumably drive composer
 		// themselves, so we leave it null and skip the autoload regeneration.
 		if ( null === $api_dir && null === $composer_working_dir ) {
-			$composer_working_dir = realpath( __DIR__ . '/../../../../..' );
+			$composer_working_dir = realpath( __DIR__ . '/../..' );
 		}
 		$this->composer_working_dir = $composer_working_dir;
 	}
@@ -277,8 +277,14 @@ class ApiBuilder {
 			if ( false === chdir( $this->composer_working_dir ) ) {
 				echo "Warning: could not chdir to {$this->composer_working_dir}; skipping autoloader regeneration.\n";
 			} else {
+				// --dev so the autoload-dev PSR-4 entries (notably
+				// `Automattic\WooCommerce\Tests\` → `tests/php/src/`) stay
+				// registered. Otherwise a subsequent `build:api:test` run
+				// can't reflect the dummy-API fixtures and aborts. This is
+				// a design-time CLI script; dev autoload is a strict
+				// superset of prod, so there's no downside.
 				// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.system_calls_passthru -- design-time CLI script; never runs in a web context.
-				passthru( 'composer dump-autoload', $code );
+				passthru( 'composer dump-autoload --dev', $code );
 				if ( false !== $original_cwd ) {
 					chdir( $original_cwd );
 				}
@@ -2070,8 +2076,8 @@ class ApiBuilder {
 		$code .= "// THIS FILE IS AUTO-GENERATED. DO NOT EDIT MANUALLY.\n\n";
 		$code .= "namespace {$namespace};\n\n";
 		$code .= "use {$node_type_namespace}\\{$node_type_class} as {$node_type_alias};\n";
-		$code .= "use Automattic\\WooCommerce\\Internal\\Api\\Schema\\ObjectType;\n";
-		$code .= "use Automattic\\WooCommerce\\Internal\\Api\\Schema\\Type;\n\n";
+		$code .= "use Automattic\\WooCommerce\\Api\\Infrastructure\\Schema\\ObjectType;\n";
+		$code .= "use Automattic\\WooCommerce\\Api\\Infrastructure\\Schema\\Type;\n\n";
 		$code .= "class {$connection_class_name} {\n";
 		$code .= "\tprivate static ?ObjectType \$instance = null;\n\n";
 		$code .= "\tpublic static function get(): ObjectType {\n";
@@ -2114,8 +2120,8 @@ class ApiBuilder {
 		$code .= "// THIS FILE IS AUTO-GENERATED. DO NOT EDIT MANUALLY.\n\n";
 		$code .= "namespace {$namespace};\n\n";
 		$code .= "use {$node_type_namespace}\\{$node_type_class} as {$node_type_alias};\n";
-		$code .= "use Automattic\\WooCommerce\\Internal\\Api\\Schema\\ObjectType;\n";
-		$code .= "use Automattic\\WooCommerce\\Internal\\Api\\Schema\\Type;\n\n";
+		$code .= "use Automattic\\WooCommerce\\Api\\Infrastructure\\Schema\\ObjectType;\n";
+		$code .= "use Automattic\\WooCommerce\\Api\\Infrastructure\\Schema\\Type;\n\n";
 		$code .= "class {$edge_class_name} {\n";
 		$code .= "\tprivate static ?ObjectType \$instance = null;\n\n";
 		$code .= "\tpublic static function get(): ObjectType {\n";
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/StalenessChecker.php b/plugins/woocommerce/bin/api-builder/StalenessChecker.php
similarity index 93%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/StalenessChecker.php
rename to plugins/woocommerce/bin/api-builder/StalenessChecker.php
index 4e8b4d65dfa..f81a30a3048 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/StalenessChecker.php
+++ b/plugins/woocommerce/bin/api-builder/StalenessChecker.php
@@ -2,7 +2,7 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api\DesignTime\Scripts;
+namespace Automattic\WooCommerce\Api\Infrastructure\DesignTime;

 /**
  * Checks whether the autogenerated API code is stale and needs rebuilding.
@@ -23,8 +23,8 @@ class StalenessChecker {
 	 * @param string|null $autogenerated_dir Absolute path to the autogenerated output directory. Defaults to WooCommerce core's `src/Internal/Api/Autogenerated`.
 	 */
 	public static function is_stale( ?string $api_dir = null, ?string $autogenerated_dir = null ): bool {
-		$api_dir           ??= __DIR__ . '/../../../../Api';
-		$autogenerated_dir ??= __DIR__ . '/../../Autogenerated';
+		$api_dir           ??= __DIR__ . '/../../src/Api';
+		$autogenerated_dir ??= __DIR__ . '/../../src/Internal/Api/Autogenerated';

 		$hash_file = $autogenerated_dir . '/' . self::HASH_FILE_NAME;
 		if ( ! file_exists( $hash_file ) ) {
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/build-api.php b/plugins/woocommerce/bin/api-builder/build-api.php
similarity index 96%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/build-api.php
rename to plugins/woocommerce/bin/api-builder/build-api.php
index e1cc261de0c..de8cfc64c98 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/build-api.php
+++ b/plugins/woocommerce/bin/api-builder/build-api.php
@@ -84,9 +84,9 @@ if ( PHP_VERSION_ID < 80100 ) {
 	exit( 2 );
 }

-require_once __DIR__ . '/../../../../../vendor/autoload.php';
+require_once __DIR__ . '/../../vendor/autoload.php';

-use Automattic\WooCommerce\Internal\Api\DesignTime\Scripts\ApiBuilder;
+use Automattic\WooCommerce\Api\Infrastructure\DesignTime\ApiBuilder;

 $skip_linter = isset( $options['no-linter'] );

diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/check-api-staleness.php b/plugins/woocommerce/bin/api-builder/check-api-staleness.php
similarity index 76%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/check-api-staleness.php
rename to plugins/woocommerce/bin/api-builder/check-api-staleness.php
index 356375b9b84..4f28e4b0a80 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Scripts/check-api-staleness.php
+++ b/plugins/woocommerce/bin/api-builder/check-api-staleness.php
@@ -13,9 +13,9 @@ if ( PHP_VERSION_ID < 80100 ) {
 	exit( 2 );
 }

-require_once __DIR__ . '/../../../../../vendor/autoload.php';
+require_once __DIR__ . '/../../vendor/autoload.php';

-use Automattic\WooCommerce\Internal\Api\DesignTime\Scripts\StalenessChecker;
+use Automattic\WooCommerce\Api\Infrastructure\DesignTime\StalenessChecker;

 if ( StalenessChecker::is_stale() ) {
 	fwrite( STDERR, "ERROR: Generated GraphQL API code is out of date.\n" );
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/EnumTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/EnumTypeTemplate.php
similarity index 97%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/EnumTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/EnumTypeTemplate.php
index 3fe3d00df54..7bca2055ffb 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/EnumTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/EnumTypeTemplate.php
@@ -23,7 +23,7 @@ declare(strict_types=1);
 namespace <?php echo $namespace; ?>;

 use <?php echo $enum_fqcn; ?> as <?php echo $enum_alias; ?>;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class <?php echo $class_name; ?> {
 	private static ?EnumType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/GraphQLControllerTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/GraphQLControllerTemplate.php
similarity index 87%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/GraphQLControllerTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/GraphQLControllerTemplate.php
index b2d50d5b903..21bd71e763b 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/GraphQLControllerTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/GraphQLControllerTemplate.php
@@ -2,8 +2,8 @@
 /**
  * Template for generating the GraphQLController subclass.
  *
- * Emitted by ApiBuilder. The generated class extends the hand-written
- * core controller in Automattic\WooCommerce\Internal\Api and overrides
+ * Emitted by ApiBuilder. The generated class extends the public base
+ * controller in Automattic\WooCommerce\Api\Infrastructure and overrides
  * build_schema() to reference the root types that ApiBuilder has just
  * generated in the same autogenerated namespace.
  *
@@ -29,9 +29,9 @@ declare(strict_types=1);

 namespace <?php echo $namespace; ?>;

-use Automattic\WooCommerce\Internal\Api\Schema\Schema;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Schema;

-class GraphQLController extends \Automattic\WooCommerce\Internal\Api\GraphQLController {
+class GraphQLController extends \Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase {
 	protected function build_schema(): Schema {
 		return new Schema(
 			array(
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/InputObjectTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/InputObjectTypeTemplate.php
similarity index 96%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/InputObjectTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/InputObjectTypeTemplate.php
index 123c37f8c43..3335b37f6bc 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/InputObjectTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/InputObjectTypeTemplate.php
@@ -49,8 +49,8 @@ $use_statements             = array_values(
 <?php foreach ( $use_statements as $use ) : ?>
 use <?php echo $use; ?>;
 <?php endforeach; ?>
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class <?php echo $class_name; ?> {
 	private static ?InputObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/InterfaceTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/InterfaceTypeTemplate.php
similarity index 97%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/InterfaceTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/InterfaceTypeTemplate.php
index 83cdd7fcf4e..c9feb70dd83 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/InterfaceTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/InterfaceTypeTemplate.php
@@ -50,8 +50,8 @@ $use_statements             = array_values(
 <?php foreach ( $use_statements as $use ) : ?>
 use <?php echo $use; ?>;
 <?php endforeach; ?>
-use Automattic\WooCommerce\Internal\Api\Schema\InterfaceType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InterfaceType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class <?php echo $class_name; ?> {
 	private static ?InterfaceType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/MutationResolverTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/MutationResolverTemplate.php
similarity index 100%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/MutationResolverTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/MutationResolverTemplate.php
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/ObjectTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/ObjectTypeTemplate.php
similarity index 92%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/ObjectTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/ObjectTypeTemplate.php
index eb2348a59b0..2d405157b73 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/ObjectTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/ObjectTypeTemplate.php
@@ -36,7 +36,7 @@ foreach ( $fields as $f ) {
 $reserved_short_names = array( 'ObjectType', 'Type' );
 if ( $has_paginated_connection ) {
 	$reserved_short_names[] = 'Connection';
-	$reserved_short_names[] = 'Utils';
+	$reserved_short_names[] = 'ResolverHelpers';
 }
 // PHP class-name resolution (including `use`) is case-insensitive, so the
 // collision check has to be too — a caller-supplied `Foo\resolveinfo` would
@@ -62,11 +62,11 @@ $use_statements             = array_values(
 use <?php echo $use; ?>;
 <?php endforeach; ?>
 <?php if ( $has_paginated_connection ) : ?>
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Api\Pagination\Connection;
-use Automattic\WooCommerce\Internal\Api\Utils;
 <?php endif; ?>
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class <?php echo $class_name; ?> {
 	private static ?ObjectType $instance = null;
@@ -133,8 +133,8 @@ class <?php echo $class_name; ?> {
 							'deprecationReason' => '<?php echo addslashes( $field['deprecation_reason'] ); ?>',
 <?php endif; ?>
 	<?php if ( ! empty( $field['paginated_connection'] ) ) : ?>
-							'complexity' => Utils::complexity_from_pagination(...),
-							'resolve'    => fn( $parent, array $args ): Connection => Utils::translate_exceptions( fn() => $parent-><?php echo $field['name']; ?>->slice( $args ) ),
+							'complexity' => ResolverHelpers::complexity_from_pagination(...),
+							'resolve'    => fn( $parent, array $args ): Connection => ResolverHelpers::translate_exceptions( fn() => $parent-><?php echo $field['name']; ?>->slice( $args ) ),
 <?php endif; ?>
 						),
 <?php endforeach; ?>
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/PageInfoTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/PageInfoTypeTemplate.php
similarity index 87%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/PageInfoTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/PageInfoTypeTemplate.php
index 53c344ebe41..a450d00a83c 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/PageInfoTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/PageInfoTypeTemplate.php
@@ -13,8 +13,8 @@ declare(strict_types=1);

 namespace <?php echo $namespace; ?>;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class PageInfo {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/QueryResolverTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/QueryResolverTemplate.php
similarity index 91%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/QueryResolverTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/QueryResolverTemplate.php
index e42972dcac0..d304f6635bd 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/QueryResolverTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/QueryResolverTemplate.php
@@ -43,14 +43,14 @@ declare(strict_types=1);
 namespace <?php echo $namespace; ?>;

 use <?php echo $command_fqcn; ?> as <?php echo $command_alias; ?>;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 <?php
 // Drop any caller-supplied import whose effective short name would collide
 // with one of the imports emitted unconditionally above and below, otherwise
 // the generated file would fail to compile ("Cannot use ... because the name
 // is already in use").
-$reserved_short_names = array( $command_alias, 'QueryInfoExtractor', 'Utils', 'ResolveInfo', 'Type' );
+$reserved_short_names = array( $command_alias, 'QueryInfoExtractor', 'ResolverHelpers', 'ResolveInfo', 'Type' );
 // PHP class-name resolution (including `use`) is case-insensitive, so the
 // collision check has to be too — a caller-supplied `Foo\resolveinfo` would
 // otherwise slip past and fail at compile time of the generated file.
@@ -74,14 +74,14 @@ $use_statements             = array_values(
 <?php foreach ( $use_statements as $use ) : ?>
 use <?php echo $use; ?>;
 <?php endforeach; ?>
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class <?php echo $class_name; ?> {
 	public static function get_field_definition(): array {
 		return array(
 <?php if ( $scalar_return ) : ?>
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
+			'type' => Type::nonNull(new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(array(
 				'name' => '<?php echo $class_name; ?>Result',
 				'fields' => array(
 					'result' => array( 'type' => <?php echo $return_type_expr; ?> ),
@@ -121,7 +121,7 @@ class <?php echo $class_name; ?> {
 <?php endforeach; ?>
 			),
 <?php if ( $has_connection_of ) : ?>
-			'complexity' => Utils::complexity_from_pagination(...),
+			'complexity' => ResolverHelpers::complexity_from_pagination(...),
 <?php endif; ?>
 			'resolve' => array( self::class, 'resolve' ),
 		);
@@ -132,7 +132,7 @@ class <?php echo $class_name; ?> {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 <?php endif; ?>
@@ -151,9 +151,9 @@ $pagination_fqcn = 'Automattic\\WooCommerce\\Api\\Pagination\\PaginationParams';
 foreach ( $execute_params as $param ) :
 	if ( ! empty( $param['unroll'] ) && $param['unroll']['fqcn'] === $pagination_fqcn ) :
 ?>
-		$execute_args['<?php echo $param['name']; ?>'] = Utils::create_pagination_params( $args );
+		$execute_args['<?php echo $param['name']; ?>'] = ResolverHelpers::create_pagination_params( $args );
 <?php elseif ( ! empty( $param['unroll'] ) ) : ?>
-		$execute_args['<?php echo $param['name']; ?>'] = Utils::create_input(
+		$execute_args['<?php echo $param['name']; ?>'] = ResolverHelpers::create_input(
 			fn() => new \<?php echo $param['unroll']['fqcn']; ?>(
 <?php foreach ( $param['unroll']['properties'] as $uprop ) : ?>
 				<?php echo $uprop['name']; ?>: <?php echo $uprop['value_expr']; ?>,
@@ -176,7 +176,7 @@ foreach ( $execute_params as $param ) :
 <?php endforeach; ?>

 <?php if ( $has_authorize ) : ?>
-		if ( ! Utils::authorize_command( $command, array(
+		if ( ! ResolverHelpers::authorize_command( $command, array(
 <?php foreach ( $authorize_param_names as $name ) : ?>
 			'<?php echo $name; ?>' => $execute_args['<?php echo $name; ?>'],
 <?php endforeach; ?>
@@ -190,11 +190,11 @@ foreach ( $execute_params as $param ) :
 			'_preauthorized' => <?php echo $preauthorized_expr; ?>,
 <?php endif; ?>
 		) ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 <?php endif; ?>
-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 <?php if ( $scalar_return ) : ?>
 		return array( 'result' => $result );
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/RootMutationTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/RootMutationTypeTemplate.php
similarity index 93%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/RootMutationTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/RootMutationTypeTemplate.php
index d0ed1702515..e73a4216383 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/RootMutationTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/RootMutationTypeTemplate.php
@@ -17,7 +17,7 @@ namespace <?php echo $namespace; ?>;
 <?php foreach ( $mutations as $mutation ) : ?>
 use <?php echo $mutation['fqcn']; ?>;
 <?php endforeach; ?>
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;

 class RootMutationType {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/RootQueryTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/RootQueryTypeTemplate.php
similarity index 87%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/RootQueryTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/RootQueryTypeTemplate.php
index 55c8c3531ff..92635e958f4 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/RootQueryTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/RootQueryTypeTemplate.php
@@ -3,7 +3,7 @@
  * Template for generating the RootQueryType class.
  *
  * Besides the autogenerated query fields, the root `Query` type also gets the
- * hand-written `_apiMetadata` field contributed by {@see \Automattic\WooCommerce\Internal\Api\MetadataController}.
+ * hand-written `_apiMetadata` field contributed by {@see \Automattic\WooCommerce\Api\Infrastructure\MetadataController}.
  * That class lives in the shared infrastructure namespace, so plugins reusing
  * this template inherit the metadata-discovery field for free.
  *
@@ -22,8 +22,8 @@ namespace <?php echo $namespace; ?>;
 <?php foreach ( $queries as $query ) : ?>
 use <?php echo $query['fqcn']; ?>;
 <?php endforeach; ?>
-use Automattic\WooCommerce\Internal\Api\MetadataController;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\MetadataController;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;

 class RootQueryType {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/ScalarTypeTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/ScalarTypeTemplate.php
similarity index 81%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/ScalarTypeTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/ScalarTypeTemplate.php
index 42b6011405f..900a2fd27e7 100644
--- a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/ScalarTypeTemplate.php
+++ b/plugins/woocommerce/bin/api-builder/code-templates/ScalarTypeTemplate.php
@@ -22,7 +22,7 @@ declare(strict_types=1);
 namespace <?php echo $namespace; ?>;

 use <?php echo $scalar_fqcn; ?> as <?php echo $scalar_alias; ?>;
-use Automattic\WooCommerce\Internal\Api\Schema\CustomScalarType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\CustomScalarType;

 class <?php echo $class_name; ?> {
 	private static ?CustomScalarType $instance = null;
@@ -47,18 +47,18 @@ class <?php echo $class_name; ?> {
 						try {
 							return <?php echo $scalar_alias; ?>::parse( $value );
 						} catch ( \InvalidArgumentException $e ) {
-							throw new \Automattic\WooCommerce\Internal\Api\Schema\Error( $e->getMessage() );
+							throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error( $e->getMessage() );
 						}
 					},
 					'parseLiteral' => function ( $value_node, ?array $variables = null ) {
-						if ( $value_node instanceof \Automattic\WooCommerce\Internal\Api\Schema\AST\StringValueNode ) {
+						if ( $value_node instanceof \Automattic\WooCommerce\Api\Infrastructure\Schema\AST\StringValueNode ) {
 							try {
 								return <?php echo $scalar_alias; ?>::parse( $value_node->value );
 							} catch ( \InvalidArgumentException $e ) {
-								throw new \Automattic\WooCommerce\Internal\Api\Schema\Error( $e->getMessage() );
+								throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error( $e->getMessage() );
 							}
 						}
-						throw new \Automattic\WooCommerce\Internal\Api\Schema\Error(
+						throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error(
 							'<?php echo $graphql_name; ?> must be a string, got: ' . $value_node->kind
 						);
 					},
diff --git a/plugins/woocommerce/src/Internal/Api/DesignTime/Templates/TypeRegistryTemplate.php b/plugins/woocommerce/bin/api-builder/code-templates/TypeRegistryTemplate.php
similarity index 100%
rename from plugins/woocommerce/src/Internal/Api/DesignTime/Templates/TypeRegistryTemplate.php
rename to plugins/woocommerce/bin/api-builder/code-templates/TypeRegistryTemplate.php
diff --git a/plugins/woocommerce/changelog/65151-make-graphql-code-accessible-externally-not-internal b/plugins/woocommerce/changelog/65151-make-graphql-code-accessible-externally-not-internal
new file mode 100644
index 00000000000..78256c9d986
--- /dev/null
+++ b/plugins/woocommerce/changelog/65151-make-graphql-code-accessible-externally-not-internal
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Move GraphQL infrastructure classes used by autogenerated code out of the `Internal` namespace into `Api\Infrastructure`
\ No newline at end of file
diff --git a/plugins/woocommerce/composer.json b/plugins/woocommerce/composer.json
index d299ff3ae8b..2c2c90d3e9f 100644
--- a/plugins/woocommerce/composer.json
+++ b/plugins/woocommerce/composer.json
@@ -110,13 +110,14 @@
 			"src/StoreApi/functions.php",
 			"src/Blocks/Domain/Services/functions.php",
 			"src/Deprecated.php",
-			"src/Internal/Api/Schema/aliases.php"
+			"src/Api/Infrastructure/Schema/aliases.php"
 		]
 	},
 	"autoload-dev": {
 		"psr-4": {
 			"Automattic\\WooCommerce\\Tests\\": "tests/php/src/",
-			"Automattic\\WooCommerce\\Testing\\Tools\\": "tests/Tools/"
+			"Automattic\\WooCommerce\\Testing\\Tools\\": "tests/Tools/",
+			"Automattic\\WooCommerce\\Api\\Infrastructure\\DesignTime\\": "bin/api-builder/"
 		},
 		"classmap": [
 			"tests/legacy/unit-tests/rest-api/Helpers"
diff --git a/plugins/woocommerce/includes/class-woocommerce.php b/plugins/woocommerce/includes/class-woocommerce.php
index 0e2ecc4db2c..9854f4e4604 100644
--- a/plugins/woocommerce/includes/class-woocommerce.php
+++ b/plugins/woocommerce/includes/class-woocommerce.php
@@ -417,7 +417,7 @@ final class WooCommerce {
 		$container->get( Automattic\WooCommerce\Internal\ProductFilters\CacheController::class )->register();

 		// Code+GraphQL API.
-		Automattic\WooCommerce\Internal\Api\Main::register();
+		Automattic\WooCommerce\Api\Infrastructure\Main::register();

 		// Integration point between legacy reports and orders APIs (the reports caches invalidation focused).
 		\WC_Admin_Reports::register_orders_hook_handlers();
diff --git a/plugins/woocommerce/package.json b/plugins/woocommerce/package.json
index cdcbeb6438f..36a59a1d718 100644
--- a/plugins/woocommerce/package.json
+++ b/plugins/woocommerce/package.json
@@ -22,9 +22,9 @@
 		"build:project:copy-assets:email-editor": "rsync -avhW --checksum --delete --quiet ../../packages/php/email-editor/src/ packages/email-editor/src",
 		"build:project:copy-assets:blueprint": "rsync -avhW --checksum --delete --quiet ../../packages/php/blueprint/src/ packages/blueprint/src",
 		"build:project:actualize-translation-domains": "wireit",
-		"build:api": "php src/Internal/Api/DesignTime/Scripts/build-api.php",
-		"build:api:check": "php src/Internal/Api/DesignTime/Scripts/check-api-staleness.php",
-		"build:api:test": "php src/Internal/Api/DesignTime/Scripts/build-api.php --api-dir=tests/php/src/Internal/Api/Fixtures/DummyApi --autogen-dir=tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated --api-namespace='Automattic\\WooCommerce\\Tests\\Internal\\Api\\Fixtures\\DummyApi' --autogen-namespace='Automattic\\WooCommerce\\Tests\\Internal\\Api\\Fixtures\\DummyApiAutogenerated'",
+		"build:api": "php bin/api-builder/build-api.php",
+		"build:api:check": "php bin/api-builder/check-api-staleness.php",
+		"build:api:test": "php bin/api-builder/build-api.php --api-dir=tests/php/src/Internal/Api/Fixtures/DummyApi --autogen-dir=tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated --api-namespace='Automattic\\WooCommerce\\Tests\\Internal\\Api\\Fixtures\\DummyApi' --autogen-namespace='Automattic\\WooCommerce\\Tests\\Internal\\Api\\Fixtures\\DummyApiAutogenerated'",
 		"changelog": "XDEBUG_MODE=off composer install --quiet && composer exec -- changelogger",
 		"update:php": "XDEBUG_MODE=off composer update --quiet",
 		"env:destroy": "pnpm wp-env destroy",
diff --git a/plugins/woocommerce/phpcs.xml b/plugins/woocommerce/phpcs.xml
index 690df2cbe74..f7402aa7ac8 100644
--- a/plugins/woocommerce/phpcs.xml
+++ b/plugins/woocommerce/phpcs.xml
@@ -59,6 +59,7 @@
 		<exclude-pattern>tests/</exclude-pattern>
 		<exclude-pattern>src/Api/</exclude-pattern>
 		<exclude-pattern>src/Internal/Api/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>

 	<!-- The Code API and its infrastructure require PHP 8.1+. CI runs on PHP 7.4,
@@ -67,6 +68,7 @@
 	<rule ref="Generic.PHP.Syntax">
 		<exclude-pattern>src/Api/</exclude-pattern>
 		<exclude-pattern>src/Internal/Api/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>

 	<!-- PHP 8.0 `mixed` type hint is valid but not recognized by the Squiz sniff -->
@@ -98,6 +100,7 @@
 	     unavoidable in attribute definitions, autoloader closures, and generated code. -->
 	<rule ref="Universal.NamingConventions.NoReservedKeywordParameterNames">
 		<exclude-pattern>src/Api/Attributes/Parameter.php</exclude-pattern>
+		<exclude-pattern>src/Api/Infrastructure/</exclude-pattern>
 		<exclude-pattern>src/Internal/Api/</exclude-pattern>
 	</rule>

@@ -163,6 +166,7 @@
 		<exclude-pattern>tests/</exclude-pattern>
 		<exclude-pattern>src/</exclude-pattern>
 		<exclude-pattern>tests/php/src/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>

 	<rule ref="Squiz.Classes.ClassFileName">
@@ -188,6 +192,7 @@
 		<exclude-pattern>src/</exclude-pattern>
 		<exclude-pattern>tests/php</exclude-pattern>
 		<exclude-pattern>tests/Tools/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>

 	<rule ref="Squiz.Commenting.FileComment.MissingPackageTag">
@@ -233,14 +238,14 @@
 	</rule>
 	<rule ref="WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase">
 		<exclude-pattern>src/Internal/Api/Autogenerated/</exclude-pattern>
-		<exclude-pattern>src/Internal/Api/GraphQLController.php</exclude-pattern>
-		<exclude-pattern>src/Internal/Api/QueryInfoExtractor.php</exclude-pattern>
+		<exclude-pattern>src/Api/Infrastructure/GraphQLControllerBase.php</exclude-pattern>
+		<exclude-pattern>src/Api/Infrastructure/QueryInfoExtractor.php</exclude-pattern>
 	</rule>

 	<!-- API build scripts use empty if/elseif for intentional no-ops (e.g. enum
 	     properties need no conversion) with a comment explaining why. -->
 	<rule ref="Generic.CodeAnalysis.EmptyStatement">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>

 	<!-- Autogenerated code: suppress additional rules -->
@@ -250,72 +255,74 @@

 	<!-- API templates: suppress rules that don't apply to PHP templates -->
 	<rule ref="Generic.PHP.RequireStrictTypes">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="PSR12.Files.FileHeader">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="Generic.Commenting">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="Squiz.Commenting">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.PHP.DiscouragedPHPFunctions.serialize_var_export">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.CodeAnalysis.AssignmentInTernaryCondition">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.PHP.DontExtract">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.Security.EscapeOutput">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.PHP.YodaConditions">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.PHP.DevelopmentFunctions">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="Generic.WhiteSpace.ScopeIndent">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.WP.GlobalVariablesOverride">
-		<exclude-pattern>src/Internal/Api/DesignTime/Templates/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/code-templates/</exclude-pattern>
 	</rule>

 	<!-- API build scripts: suppress WordPress-specific rules (CLI-only code) -->
 	<rule ref="WordPress.PHP.DiscouragedPHPFunctions.system_calls_exec">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.WP.AlternativeFunctions">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
+		<exclude-pattern>tests/php/src/Api/Infrastructure/DesignTime/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.Security.EscapeOutput">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.PHP.YodaConditions">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.PHP.DontExtract">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>
 	<rule ref="WordPress.PHP.DevelopmentFunctions">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>
 	<rule ref="Generic.Commenting">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>
 	<rule ref="Squiz.Commenting">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
+		<exclude-pattern>tests/php/src/Api/Infrastructure/DesignTime/</exclude-pattern>
 	</rule>
 	<rule ref="Universal.NamingConventions.NoReservedKeywordParameterNames">
-		<exclude-pattern>src/Internal/Api/DesignTime/Scripts/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>
 	<rule ref="WooCommerce.Functions.InternalInjectionMethod">
-		<exclude-pattern>src/Internal/Api/DesignTime/</exclude-pattern>
+		<exclude-pattern>bin/api-builder/</exclude-pattern>
 	</rule>

 	<!-- Temporary -->
diff --git a/plugins/woocommerce/phpunit.xml b/plugins/woocommerce/phpunit.xml
index 2495107ab14..16a67826918 100644
--- a/plugins/woocommerce/phpunit.xml
+++ b/plugins/woocommerce/phpunit.xml
@@ -23,9 +23,11 @@
 			<directory suffix=".php">./tests/php</directory>
 			<exclude>./tests/php/helpers</exclude>
 			<exclude>./tests/php/src/Blocks/BlockPatterns/patterns</exclude>
+			<exclude>./tests/php/src/Api/Infrastructure</exclude>
 			<exclude>./tests/php/src/Internal/Api</exclude>
 		</testsuite>
 		<testsuite name="wc-phpunit-graphql-infra">
+			<directory suffix=".php">./tests/php/src/Api/Infrastructure</directory>
 			<directory suffix=".php">./tests/php/src/Internal/Api</directory>
 		</testsuite>

@@ -38,6 +40,7 @@
 			<directory suffix=".php">./tests/php</directory>
 			<exclude>./tests/php/helpers</exclude>
 			<exclude>./tests/php/src/Blocks/BlockPatterns/patterns</exclude>
+			<exclude>./tests/php/src/Api/Infrastructure</exclude>
 			<exclude>./tests/php/src/Internal/Api</exclude>
 		</testsuite>
 		<testsuite name="wc-phpunit-full">
diff --git a/plugins/woocommerce/src/Internal/Api/GraphQLController.php b/plugins/woocommerce/src/Api/Infrastructure/GraphQLControllerBase.php
similarity index 97%
rename from plugins/woocommerce/src/Internal/Api/GraphQLController.php
rename to plugins/woocommerce/src/Api/Infrastructure/GraphQLControllerBase.php
index b814a3fb554..080193abcef 100644
--- a/plugins/woocommerce/src/Internal/Api/GraphQLController.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/GraphQLControllerBase.php
@@ -2,25 +2,36 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api;
+namespace Automattic\WooCommerce\Api\Infrastructure;

 use Automattic\WooCommerce\Api\ApiException;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Schema;
 use Automattic\WooCommerce\Api\Utils\SchemaHandle;
+use Automattic\WooCommerce\Internal\Api\QueryCache;
+use Automattic\WooCommerce\Internal\Api\QueryComplexityRule;
+use Automattic\WooCommerce\Internal\Api\QueryDepthRule;
+use Automattic\WooCommerce\Internal\Api\StatusResolverFailedException;
+use Automattic\WooCommerce\Vendor\GraphQL\Error\DebugFlag;
 use Automattic\WooCommerce\Vendor\GraphQL\GraphQL;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\DocumentNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\FieldNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\InlineFragmentNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\OperationDefinitionNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\SelectionSetNode;
-use Automattic\WooCommerce\Vendor\GraphQL\Type\Schema;
-use Automattic\WooCommerce\Vendor\GraphQL\Error\DebugFlag;
 use Automattic\WooCommerce\Vendor\GraphQL\Validator\DocumentValidator;
 use Automattic\WooCommerce\Vendor\GraphQL\Validator\Rules\DisableIntrospection;

 /**
  * Handles incoming GraphQL requests over the WooCommerce REST API.
+ *
+ * Abstract: the autogenerated `GraphQLController` subclass emitted by
+ * ApiBuilder (both for WooCommerce core and for sibling plugins reusing this
+ * infrastructure) is the concrete class. The public surface plugins extend
+ * is engine-decoupled — the abstract {@see self::build_schema()} returns
+ * {@see Schema}, a stable subclass of the underlying engine's schema type,
+ * so a future engine swap doesn't break already-committed autogen trees.
  */
-abstract class GraphQLController {
+abstract class GraphQLControllerBase {
 	/**
 	 * Default nesting-depth limit applied when the option is unset or non-positive.
 	 *
@@ -52,7 +63,7 @@ abstract class GraphQLController {
 	 * Regex matching one valid path segment of the endpoint URL.
 	 *
 	 * Constrained to the character class WordPress REST routes accept
-	 * (alphanumerics, underscores, hyphens). Shared with {@see Settings::sanitize_endpoint_url()}
+	 * (alphanumerics, underscores, hyphens). Shared with {@see \Automattic\WooCommerce\Internal\Api\Settings::sanitize_endpoint_url()}
 	 * so the UI sanitizer and the controller-side fallback stay in lockstep.
 	 */
 	public const ENDPOINT_URL_SEGMENT_PATTERN = '/^[A-Za-z0-9_\-]+$/';
@@ -170,7 +181,7 @@ abstract class GraphQLController {
 	 * Requires at least two non-empty path segments (so register_rest_route()
 	 * has both a namespace and a route), each matching
 	 * {@see self::ENDPOINT_URL_SEGMENT_PATTERN}. Mirrors the rules enforced on
-	 * save by {@see Settings::sanitize_endpoint_url()}, so values that bypass
+	 * save by {@see \Automattic\WooCommerce\Internal\Api\Settings::sanitize_endpoint_url()}, so values that bypass
 	 * the UI (e.g. CLI-set options) get the same treatment.
 	 *
 	 * @param string $value Endpoint URL with surrounding slashes already stripped.
diff --git a/plugins/woocommerce/src/Internal/Api/Main.php b/plugins/woocommerce/src/Api/Infrastructure/Main.php
similarity index 93%
rename from plugins/woocommerce/src/Internal/Api/Main.php
rename to plugins/woocommerce/src/Api/Infrastructure/Main.php
index 48c2d30d70c..6cce34fea27 100644
--- a/plugins/woocommerce/src/Internal/Api/Main.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/Main.php
@@ -2,8 +2,13 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api;
+namespace Automattic\WooCommerce\Api\Infrastructure;

+use Automattic\WooCommerce\Internal\Api\Autogenerated;
+use Automattic\WooCommerce\Internal\Api\GraphQLEndpointRegistrar;
+use Automattic\WooCommerce\Internal\Api\OpcacheFileExpiry;
+use Automattic\WooCommerce\Internal\Api\QueryCache;
+use Automattic\WooCommerce\Internal\Api\Settings;
 use Automattic\WooCommerce\Utilities\FeaturesUtil;

 /**
@@ -11,8 +16,9 @@ use Automattic\WooCommerce\Utilities\FeaturesUtil;
  *
  * This class is intentionally free of PHP 8.0+ syntax so that it can be
  * loaded and called on PHP 7.4 without parse errors. The PHP-8.1-only
- * classes (GraphQLController, QueryCache, etc.) are resolved lazily from
- * the DI container only after is_enabled() confirms PHP 8.1+ is available.
+ * classes (GraphQLControllerBase, QueryCache, etc.) are resolved lazily
+ * from the DI container only after is_enabled() confirms PHP 8.1+ is
+ * available.
  */
 class Main {
 	/**
@@ -202,11 +208,11 @@ class Main {
 	 * can invoke this unconditionally from inside their own rest_api_init
 	 * handler.
 	 *
-	 * @param string $controller_class_name Fully-qualified name of a subclass of GraphQLController.
+	 * @param string $controller_class_name Fully-qualified name of a subclass of GraphQLControllerBase.
 	 *
-	 * @throws \InvalidArgumentException If $controller_class_name does not extend GraphQLController.
+	 * @throws \InvalidArgumentException If $controller_class_name does not extend GraphQLControllerBase.
 	 */
-	public static function instantiate_graphql_controller( string $controller_class_name ): ?GraphQLController {
+	public static function instantiate_graphql_controller( string $controller_class_name ): ?GraphQLControllerBase {
 		if ( ! self::is_enabled() ) {
 			return null;
 		}
@@ -242,8 +248,8 @@ class Main {
 	 *
 	 * Plugins calling this method should guard the call with method_exists():
 	 *
-	 *     if ( method_exists( \Automattic\WooCommerce\Internal\Api\Main::class, 'register_graphql_endpoint' ) ) {
-	 *         \Automattic\WooCommerce\Internal\Api\Main::register_graphql_endpoint(
+	 *     if ( method_exists( \Automattic\WooCommerce\Api\Infrastructure\Main::class, 'register_graphql_endpoint' ) ) {
+	 *         \Automattic\WooCommerce\Api\Infrastructure\Main::register_graphql_endpoint(
 	 *             __DIR__,
 	 *             'my-plugin',
 	 *             '/graphql'
@@ -255,7 +261,7 @@ class Main {
 	 * @param string   $route                          REST route path, as passed to register_rest_route().
 	 * @param string[] $methods                        HTTP methods accepted on the endpoint. Defaults to GET + POST.
 	 *
-	 * @throws \InvalidArgumentException If no controller can be resolved from a directory argument, or if the resolved class does not extend GraphQLController.
+	 * @throws \InvalidArgumentException If no controller can be resolved from a directory argument, or if the resolved class does not extend GraphQLControllerBase.
 	 */
 	public static function register_graphql_endpoint(
 		string $plugin_dir_or_controller_class,
@@ -378,11 +384,11 @@ class Main {
 	}

 	/**
-	 * Assert that a class name resolves to a concrete GraphQLController subclass.
+	 * Assert that a class name resolves to a concrete GraphQLControllerBase subclass.
 	 *
 	 * @param string $controller_class_name Fully-qualified name of the class to validate.
 	 *
-	 * @throws \InvalidArgumentException If the class cannot be autoloaded, or does not extend GraphQLController.
+	 * @throws \InvalidArgumentException If the class cannot be autoloaded, or does not extend GraphQLControllerBase.
 	 */
 	private static function assert_is_controller_subclass( string $controller_class_name ): void {
 		// Differentiate "class does not exist" (typo / stale autoloader) from
@@ -396,12 +402,12 @@ class Main {
 				)
 			);
 		}
-		if ( ! is_subclass_of( $controller_class_name, GraphQLController::class ) ) {
+		if ( ! is_subclass_of( $controller_class_name, GraphQLControllerBase::class ) ) {
 			throw new \InvalidArgumentException(
 				sprintf(
 					'Class "%s" must extend %s.',
 					esc_html( $controller_class_name ),
-					esc_html( GraphQLController::class )
+					esc_html( GraphQLControllerBase::class )
 				)
 			);
 		}
diff --git a/plugins/woocommerce/src/Internal/Api/MetadataController.php b/plugins/woocommerce/src/Api/Infrastructure/MetadataController.php
similarity index 90%
rename from plugins/woocommerce/src/Internal/Api/MetadataController.php
rename to plugins/woocommerce/src/Api/Infrastructure/MetadataController.php
index 73ca0b3c250..6a2d9d5d7e8 100644
--- a/plugins/woocommerce/src/Internal/Api/MetadataController.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/MetadataController.php
@@ -2,14 +2,14 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api;
+namespace Automattic\WooCommerce\Api\Infrastructure;

+use Automattic\WooCommerce\Api\Infrastructure\Schema\CustomScalarType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Error;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;
 use Automattic\WooCommerce\Api\Utils\SchemaHandle;
-use Automattic\WooCommerce\Internal\Api\Schema\CustomScalarType;
-use Automattic\WooCommerce\Internal\Api\Schema\Error;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\BooleanValueNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\FloatValueNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\IntValueNode;
@@ -24,13 +24,9 @@ use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\StringValueNode;
  * The autogenerated `RootQueryType` references this controller alongside the
  * autogenerated query resolvers, so the field appears on the root `Query`
  * type without any special wiring at the controller level. The resolver
- * delegates to {@see MetadataUtils::find()} for the schema walk and filter
- * application, then reshapes the rows so each entry is exposed as the
+ * delegates to {@see SchemaHandle::find_metadata()} for the schema walk and
+ * filter application, then reshapes the rows so each entry is exposed as the
  * `{ name, value }` pair that `MetadataEntry` expects.
- *
- * @internal Reserved for the GraphQL autogeneration infrastructure. The
- *           `_apiMetadata` field is the public-facing surface; this class is
- *           how it is wired in.
  */
 class MetadataController {
 	/**
@@ -93,10 +89,10 @@ class MetadataController {

 	/**
 	 * Resolver for the `_apiMetadata` root field. Signature matches the
-	 * webonyx resolver contract; `$root` and `$context` are unused here
+	 * engine's resolver contract; `$root` and `$context` are unused here
 	 * (root operations have no parent, and metadata is principal-independent).
 	 *
-	 * @param ?array      $root    Webonyx passes null for root resolvers.
+	 * @param ?array      $root    The engine passes null for root resolvers.
 	 * @param array       $args    GraphQL arguments (`name`, `type`, `field`).
 	 * @param array       $context Per-request context the controller builds.
 	 * @param ResolveInfo $info    Carries the schema instance to walk.
@@ -106,7 +102,7 @@ class MetadataController {
 		unset( $root, $context );

 		// Wrap the resolver's engine-typed schema into the same handle clients
-		// receive from `GraphQLController::get_schema()`, so the resolver and
+		// receive from `GraphQLControllerBase::get_schema()`, so the resolver and
 		// PHP-side callers share a single inspection surface.
 		$schema = new SchemaHandle( $info->schema );

@@ -208,7 +204,7 @@ class MetadataController {
 	/**
 	 * The `MetadataValue` custom scalar, accepting any GraphQL-compatible scalar.
 	 *
-	 * Webonyx's autogenerated scalar template hard-codes acceptance of string
+	 * The autogenerated scalar template hard-codes acceptance of string
 	 * literals only, so this scalar is hand-built rather than going through
 	 * ApiBuilder. `parseLiteral` walks the AST node types and `parseValue`
 	 * accepts the already-decoded PHP scalar that variables-mode delivers.
diff --git a/plugins/woocommerce/src/Internal/Api/QueryInfoExtractor.php b/plugins/woocommerce/src/Api/Infrastructure/QueryInfoExtractor.php
similarity index 95%
rename from plugins/woocommerce/src/Internal/Api/QueryInfoExtractor.php
rename to plugins/woocommerce/src/Api/Infrastructure/QueryInfoExtractor.php
index 87b44b11c73..0140ac74691 100644
--- a/plugins/woocommerce/src/Internal/Api/QueryInfoExtractor.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/QueryInfoExtractor.php
@@ -2,15 +2,15 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api;
+namespace Automattic\WooCommerce\Api\Infrastructure;

+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\ArgumentNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\FieldNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\FragmentDefinitionNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\FragmentSpreadNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\InlineFragmentNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\SelectionSetNode;
-use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\ResolveInfo;

 /**
  * Extracts a unified query info tree from a GraphQL ResolveInfo.
@@ -46,6 +46,10 @@ class QueryInfoExtractor {
 	/**
 	 * Recursively extract query info from a selection set.
 	 *
+	 * @internal Recursive helper exposed only for internal callers and tests;
+	 *           the engine-decoupled entry point for autogenerated resolvers
+	 *           is {@see self::extract_from_info()}.
+	 *
 	 * @param ?SelectionSetNode                     $selection_set   The selection set to process.
 	 * @param array                                 $variable_values Variable values for resolving arguments.
 	 * @param array<string, FragmentDefinitionNode> $fragments       Named fragment definitions from the document.
diff --git a/plugins/woocommerce/src/Internal/Api/Utils.php b/plugins/woocommerce/src/Api/Infrastructure/ResolverHelpers.php
similarity index 91%
rename from plugins/woocommerce/src/Internal/Api/Utils.php
rename to plugins/woocommerce/src/Api/Infrastructure/ResolverHelpers.php
index 57e6e8c05c4..c6dab50f503 100644
--- a/plugins/woocommerce/src/Internal/Api/Utils.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/ResolverHelpers.php
@@ -2,12 +2,19 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api;
+namespace Automattic\WooCommerce\Api\Infrastructure;
+
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Error;

 /**
  * Shared utilities for the auto-generated GraphQL resolvers.
+ *
+ * The public surface uses only {@see Schema\Error} (a stable subclass of the
+ * engine's Error) on throws/returns so generated code never imports an
+ * engine-specific symbol — a future engine switch can rewrite the bodies
+ * here without invalidating already-committed plugin trees.
  */
-class Utils {
+class ResolverHelpers {
 	/**
 	 * Compute the complexity cost of a paginated connection field.
 	 *
@@ -40,7 +47,7 @@ class Utils {
 	 * @param array $args The GraphQL field arguments.
 	 *
 	 * @return \Automattic\WooCommerce\Api\Pagination\PaginationParams
-	 * @throws \Automattic\WooCommerce\Vendor\GraphQL\Error\Error When a pagination value is out of range.
+	 * @throws Error When a pagination value is out of range.
 	 */
 	public static function create_pagination_params( array $args ): \Automattic\WooCommerce\Api\Pagination\PaginationParams {
 		return self::create_input(
@@ -64,14 +71,14 @@ class Utils {
 	 * @param callable $factory A callable that returns the constructed object.
 	 *
 	 * @return mixed The return value of the factory.
-	 * @throws \Automattic\WooCommerce\Vendor\GraphQL\Error\Error When the factory throws InvalidArgumentException.
+	 * @throws Error When the factory throws InvalidArgumentException.
 	 */
 	public static function create_input( callable $factory ): mixed {
 		// phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Not HTML; serialized as JSON.
 		try {
 			return $factory();
 		} catch ( \InvalidArgumentException $e ) {
-			throw new \Automattic\WooCommerce\Vendor\GraphQL\Error\Error(
+			throw new Error(
 				$e->getMessage(),
 				extensions: array( 'code' => 'INVALID_ARGUMENT' )
 			);
@@ -87,7 +94,7 @@ class Utils {
 	 * @param array  $execute_args Named arguments to pass to execute().
 	 *
 	 * @return mixed The return value of execute().
-	 * @throws \Automattic\WooCommerce\Vendor\GraphQL\Error\Error On any exception from the command.
+	 * @throws Error On any exception from the command.
 	 */
 	public static function execute_command( object $command, array $execute_args ): mixed {
 		return self::translate_exceptions(
@@ -102,14 +109,14 @@ class Utils {
 	 * Mirror of execute_command() for the authorize step. Needed because an
 	 * authorize() call can throw an ApiException (e.g. UnauthorizedException
 	 * when a target record does not exist); without this wrapper the
-	 * exception would propagate up to webonyx and lose its error code and
+	 * exception would propagate up to the engine and lose its error code and
 	 * user-visible message on its way through the generic error formatter.
 	 *
 	 * @param object $command        The command instance (must have an authorize() method).
 	 * @param array  $authorize_args Named arguments to pass to authorize().
 	 *
 	 * @return bool The return value of authorize().
-	 * @throws \Automattic\WooCommerce\Vendor\GraphQL\Error\Error On any exception from the authorize method.
+	 * @throws Error On any exception from the authorize method.
 	 */
 	public static function authorize_command( object $command, array $authorize_args ): bool {
 		return self::translate_exceptions(
@@ -134,9 +141,9 @@ class Utils {
 	 *
 	 * @param object $principal The resolved request principal.
 	 */
-	public static function build_authorization_error( object $principal ): \Automattic\WooCommerce\Internal\Api\Schema\Error {
+	public static function build_authorization_error( object $principal ): Error {
 		$is_anonymous = method_exists( $principal, 'is_authenticated' ) && ! $principal->is_authenticated();
-		return new \Automattic\WooCommerce\Internal\Api\Schema\Error(
+		return new Error(
 			$is_anonymous ? 'Authentication required.' : 'You do not have permission to perform this action.',
 			extensions: array( 'code' => $is_anonymous ? 'UNAUTHORIZED' : 'FORBIDDEN' )
 		);
@@ -181,7 +188,7 @@ class Utils {
 			// (recursively). All inherited sources contribute as peers; the
 			// only thing direct attributes shadow is the inherited tree as a
 			// whole. Mirrors
-			// {@see \Automattic\WooCommerce\Internal\Api\DesignTime\Scripts\ApiBuilder::resolve_authorization()}.
+			// {@see \Automattic\WooCommerce\Api\Infrastructure\DesignTime\ApiBuilder::resolve_authorization()}.
 			$visited = array();
 			$stack   = array_merge(
 				$ref->getParentClass() ? array( $ref->getParentClass() ) : array(),
@@ -219,7 +226,7 @@ class Utils {
 	 * Collect attribute instances declared on $source whose class declares an
 	 * authorization-shaped `authorize()` method.
 	 *
-	 * Mirrors {@see \Automattic\WooCommerce\Internal\Api\DesignTime\Scripts\ApiBuilder::collect_authorization_usages()}
+	 * Mirrors {@see \Automattic\WooCommerce\Api\Infrastructure\DesignTime\ApiBuilder::collect_authorization_usages()}
 	 * for the runtime path: same direct-then-inherited precedence, same
 	 * "any class with a bool-returning authorize() method qualifies" rule.
 	 *
@@ -291,7 +298,7 @@ class Utils {
 	 * @param callable $operation Callable to invoke.
 	 *
 	 * @return mixed The return value of the callable.
-	 * @throws \Automattic\WooCommerce\Vendor\GraphQL\Error\Error On any exception from the callable.
+	 * @throws Error On any exception from the callable.
 	 */
 	public static function translate_exceptions( callable $operation ): mixed {
 		// phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Not HTML; serialized as JSON.
@@ -302,7 +309,7 @@ class Utils {
 			// getErrorCode() can't be silently overridden by an extensions
 			// entry keyed 'code'. The invariant "the code on the wire
 			// equals ApiException::getErrorCode()" is worth enforcing.
-			throw new \Automattic\WooCommerce\Vendor\GraphQL\Error\Error(
+			throw new Error(
 				$e->getMessage(),
 				extensions: array_merge(
 					$e->getExtensions(),
@@ -310,12 +317,12 @@ class Utils {
 				)
 			);
 		} catch ( \InvalidArgumentException $e ) {
-			throw new \Automattic\WooCommerce\Vendor\GraphQL\Error\Error(
+			throw new Error(
 				$e->getMessage(),
 				extensions: array( 'code' => 'INVALID_ARGUMENT' )
 			);
 		} catch ( \Throwable $e ) {
-			throw new \Automattic\WooCommerce\Vendor\GraphQL\Error\Error(
+			throw new Error(
 				'An unexpected error occurred.',
 				previous: $e,
 				extensions: array( 'code' => 'INTERNAL_ERROR' )
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/CustomScalarType.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/CustomScalarType.php
similarity index 57%
rename from plugins/woocommerce/src/Internal/Api/Schema/CustomScalarType.php
rename to plugins/woocommerce/src/Api/Infrastructure/Schema/CustomScalarType.php
index c9ed0815841..9e7ce948461 100644
--- a/plugins/woocommerce/src/Internal/Api/Schema/CustomScalarType.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/CustomScalarType.php
@@ -2,20 +2,18 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api\Schema;
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;

 /**
- * Stable subclass of the webonyx CustomScalarType used by autogenerated
- * custom scalar types.
+ * Stable subclass of the underlying GraphQL engine's CustomScalarType, used
+ * by autogenerated custom scalar types.
  *
- * The constructor accepts the same associative-array config webonyx
- * documents (keys: `name`, `description`, `serialize`, `parseValue`,
- * `parseLiteral`).
+ * The constructor accepts the same associative-array config the current
+ * engine (webonyx) documents (keys: `name`, `description`, `serialize`,
+ * `parseValue`, `parseLiteral`).
  *
  * A `metadata` config key may also be provided; see
  * {@see ObjectType::get_metadata()} for the semantics.
- *
- * @internal Reserved for autogenerated resolver code.
  */
 class CustomScalarType extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\CustomScalarType {
 	/**
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/EnumType.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/EnumType.php
similarity index 60%
rename from plugins/woocommerce/src/Internal/Api/Schema/EnumType.php
rename to plugins/woocommerce/src/Api/Infrastructure/Schema/EnumType.php
index 24365992c9b..8d7acdff321 100644
--- a/plugins/woocommerce/src/Internal/Api/Schema/EnumType.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/EnumType.php
@@ -2,18 +2,17 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api\Schema;
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;

 /**
- * Stable subclass of the webonyx EnumType used by autogenerated enums.
+ * Stable subclass of the underlying GraphQL engine's EnumType, used by
+ * autogenerated enums.
  *
- * The constructor accepts the same associative-array config webonyx
- * documents (keys: `name`, `description`, `values`).
+ * The constructor accepts the same associative-array config the current
+ * engine (webonyx) documents (keys: `name`, `description`, `values`).
  *
  * A `metadata` config key may also be provided; see
  * {@see ObjectType::get_metadata()} for the semantics.
- *
- * @internal Reserved for autogenerated resolver code.
  */
 class EnumType extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\EnumType {
 	/**
diff --git a/plugins/woocommerce/src/Api/Infrastructure/Schema/Error.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/Error.php
new file mode 100644
index 00000000000..3616f33f0ae
--- /dev/null
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/Error.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;
+
+/**
+ * Stable subclass of the underlying GraphQL engine's Error, used by
+ * autogenerated resolvers when they need to surface a GraphQL-spec error
+ * directly (e.g. the UNAUTHORIZED error an autogenerated authorize()-backed
+ * resolver throws before invoking the command).
+ *
+ * Behaviour is inherited verbatim, including the named `extensions`
+ * argument that callers rely on to attach an error code.
+ */
+class Error extends \Automattic\WooCommerce\Vendor\GraphQL\Error\Error {
+}
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/InputObjectType.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/InputObjectType.php
similarity index 60%
rename from plugins/woocommerce/src/Internal/Api/Schema/InputObjectType.php
rename to plugins/woocommerce/src/Api/Infrastructure/Schema/InputObjectType.php
index 11945a6a442..e2d29e817de 100644
--- a/plugins/woocommerce/src/Internal/Api/Schema/InputObjectType.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/InputObjectType.php
@@ -2,19 +2,17 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api\Schema;
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;

 /**
- * Stable subclass of the webonyx InputObjectType used by autogenerated
- * input types.
+ * Stable subclass of the underlying GraphQL engine's InputObjectType, used
+ * by autogenerated input types.
  *
- * The constructor accepts the same associative-array config webonyx
- * documents (keys: `name`, `description`, `fields`).
+ * The constructor accepts the same associative-array config the current
+ * engine (webonyx) documents (keys: `name`, `description`, `fields`).
  *
  * A `metadata` config key may also be provided; see
  * {@see ObjectType::get_metadata()} for the semantics.
- *
- * @internal Reserved for autogenerated resolver code.
  */
 class InputObjectType extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\InputObjectType {
 	/**
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/InterfaceType.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/InterfaceType.php
similarity index 58%
rename from plugins/woocommerce/src/Internal/Api/Schema/InterfaceType.php
rename to plugins/woocommerce/src/Api/Infrastructure/Schema/InterfaceType.php
index 759b9aa7f1c..f192c260206 100644
--- a/plugins/woocommerce/src/Internal/Api/Schema/InterfaceType.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/InterfaceType.php
@@ -2,19 +2,18 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api\Schema;
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;

 /**
- * Stable subclass of the webonyx InterfaceType used by autogenerated
- * interface types.
+ * Stable subclass of the underlying GraphQL engine's InterfaceType, used by
+ * autogenerated interface types.
  *
- * The constructor accepts the same associative-array config webonyx
- * documents (keys: `name`, `description`, `fields`, `resolveType`).
+ * The constructor accepts the same associative-array config the current
+ * engine (webonyx) documents (keys: `name`, `description`, `fields`,
+ * `resolveType`).
  *
  * A `metadata` config key may also be provided; see
  * {@see ObjectType::get_metadata()} for the semantics.
- *
- * @internal Reserved for autogenerated resolver code.
  */
 class InterfaceType extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\InterfaceType {
 	/**
diff --git a/plugins/woocommerce/src/Api/Infrastructure/Schema/ObjectType.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/ObjectType.php
new file mode 100644
index 00000000000..32321ab783a
--- /dev/null
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/ObjectType.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;
+
+/**
+ * Stable subclass of the underlying GraphQL engine's ObjectType, used by
+ * autogenerated output types, pagination types and root Query/Mutation types.
+ *
+ * The constructor accepts the same associative-array config the current
+ * engine (webonyx) documents (keys: `name`, `description`, `fields`,
+ * `interfaces`). The `fields` entry is either an array or a callable
+ * returning an array of field definitions.
+ *
+ * The wrapper also recognises a `metadata` key — an associative array
+ * mapping metadata `name` => scalar `value` — that ApiBuilder emits for
+ * types carrying {@see \Automattic\WooCommerce\Api\Attributes\Metadata}
+ * attributes. The engine ignores unknown config keys, so this rides through
+ * untouched and is surfaced by {@see self::get_metadata()}.
+ */
+class ObjectType extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\ObjectType {
+	/**
+	 * Type-level metadata entries declared in the config, keyed by name.
+	 *
+	 * @return array<string, bool|int|float|string|null>
+	 */
+	public function get_metadata(): array {
+		return $this->config['metadata'] ?? array();
+	}
+}
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/README.md b/plugins/woocommerce/src/Api/Infrastructure/Schema/README.md
similarity index 87%
rename from plugins/woocommerce/src/Internal/Api/Schema/README.md
rename to plugins/woocommerce/src/Api/Infrastructure/Schema/README.md
index 3f99c9d2cc5..8fbed1cceab 100644
--- a/plugins/woocommerce/src/Internal/Api/Schema/README.md
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/README.md
@@ -6,7 +6,7 @@ This directory is the sole point of contact between autogenerated GraphQL code a

 The dual-code API architecture treats the GraphQL engine as an implementation detail: given a set of code-API classes under `src/Api/`, ApiBuilder regenerates the autogenerated tree, and switching engines should be a matter of updating templates and regenerating. That contract only holds as long as the autogenerated output never references engine-specific symbols directly.

-Sibling WooCommerce plugins that reuse this infrastructure commit their autogenerated trees to their own repos. If those trees imported from `Automattic\WooCommerce\Vendor\GraphQL\*`, an engine switch in WooCommerce would break every already-committed plugin. Routing every engine reference through this namespace prevents that: the generator emits imports from `Automattic\WooCommerce\Internal\Api\Schema\*` only, and the classes here translate to whichever engine is current.
+WooCommerce plugins that reuse this infrastructure commit their autogenerated trees to their own repos. If those trees imported from `Automattic\WooCommerce\Vendor\GraphQL\*`, an engine switch in WooCommerce would break every already-committed plugin. Routing every engine reference through this namespace prevents that: the generator emits imports from `Automattic\WooCommerce\Api\Infrastructure\Schema\*` only, and the classes here translate to whichever engine is current.

 ## What's in here

@@ -35,7 +35,7 @@ Every symbol a generated resolver, type, or root-type class can touch at runtime

 - **No implementation logic in the subclasses.** They exist to be stable FQCNs, nothing more. Behaviour that would diverge from the webonyx parent is engine-specific and belongs in a per-engine adapter, not in the surface.
 - **Generated code references this namespace only, never `Vendor\GraphQL\*`.** If a template needs a webonyx symbol that isn't here, add it here first.
-- **Versioning is implicit in the namespace.** If a future change would break already-committed plugin code, add a sibling namespace (e.g. `Internal\Api\Schema\V2`) and teach ApiBuilder to emit against it; keep the current surface until the last dependent plugin has migrated.
+- **Versioning is implicit in the namespace.** If a future change would break already-committed plugin code, add a sibling namespace (e.g. `Api\Infrastructure\Schema\V2`) and teach ApiBuilder to emit against it; keep the current surface until the last dependent plugin has migrated.

 ## Adding a new symbol

diff --git a/plugins/woocommerce/src/Api/Infrastructure/Schema/Schema.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/Schema.php
new file mode 100644
index 00000000000..ff6f5e2edeb
--- /dev/null
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/Schema.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;
+
+/**
+ * Stable subclass of the underlying GraphQL engine's Schema, used by
+ * autogenerated GraphQLController subclasses.
+ *
+ * The constructor accepts the same associative-array config the current
+ * engine (webonyx) documents (keys: `query`, `mutation`, `types`, etc.).
+ * Extending the engine class means its executor treats an instance of this
+ * class identically to its own parent, so no adaptation is needed at runtime.
+ */
+class Schema extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Schema {
+}
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/Type.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/Type.php
similarity index 75%
rename from plugins/woocommerce/src/Internal/Api/Schema/Type.php
rename to plugins/woocommerce/src/Api/Infrastructure/Schema/Type.php
index daab5afaf28..8c199891a16 100644
--- a/plugins/woocommerce/src/Internal/Api/Schema/Type.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/Type.php
@@ -2,7 +2,7 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Internal\Api\Schema;
+namespace Automattic\WooCommerce\Api\Infrastructure\Schema;

 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\Type as WebonyxType;

@@ -10,14 +10,12 @@ use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\Type as WebonyxType;
  * Static facade for GraphQL scalar types and type modifiers referenced by
  * autogenerated resolvers.
  *
- * Autogenerated code emitted by ApiBuilder only touches webonyx through
- * this (and the other classes in the Internal\Api\Schema namespace), so
- * the underlying GraphQL engine can be swapped without invalidating
- * already-committed generated code. Return types are intentionally
- * omitted so a future migration can change the concrete return type
- * without breaking callers.
- *
- * @internal Reserved for autogenerated resolver code.
+ * Autogenerated code emitted by ApiBuilder only touches the underlying
+ * GraphQL engine through this (and the other classes in the
+ * Api\Infrastructure\Schema namespace), so the engine can be swapped without
+ * invalidating already-committed generated code. Return types are
+ * intentionally omitted so a future migration can change the concrete
+ * return type without breaking callers.
  */
 final class Type {
 	/**
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/aliases.php b/plugins/woocommerce/src/Api/Infrastructure/Schema/aliases.php
similarity index 68%
rename from plugins/woocommerce/src/Internal/Api/Schema/aliases.php
rename to plugins/woocommerce/src/Api/Infrastructure/Schema/aliases.php
index 6b3db75393d..ce2a43b89e1 100644
--- a/plugins/woocommerce/src/Internal/Api/Schema/aliases.php
+++ b/plugins/woocommerce/src/Api/Infrastructure/Schema/aliases.php
@@ -1,28 +1,26 @@
 <?php
 /**
- * Class-alias bootstrap for the Internal\Api\Schema surface.
+ * Class-alias bootstrap for the Api\Infrastructure\Schema surface.
  *
  * Some symbols in the surface — ResolveInfo and StringValueNode — cannot be
  * subclasses because the GraphQL engine constructs them itself and hands them
  * to resolver code. A subclass would be a distinct type and fail resolver
  * parameter type-hint checks. Instead we register them as class_alias of
- * their webonyx counterparts so the two FQCNs resolve to the same class.
+ * their engine counterparts so the two FQCNs resolve to the same class.
  *
  * This file is loaded eagerly via composer's `autoload.files` entry (which
  * the Jetpack autoloader in turn exposes through its filemap), so the aliases
  * are available before any resolver is invoked.
- *
- * @internal Reserved for the GraphQL autogeneration infrastructure.
  */

 declare(strict_types=1);

 class_alias(
 	\Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\ResolveInfo::class,
-	'Automattic\\WooCommerce\\Internal\\Api\\Schema\\ResolveInfo'
+	'Automattic\\WooCommerce\\Api\\Infrastructure\\Schema\\ResolveInfo'
 );

 class_alias(
 	\Automattic\WooCommerce\Vendor\GraphQL\Language\AST\StringValueNode::class,
-	'Automattic\\WooCommerce\\Internal\\Api\\Schema\\AST\\StringValueNode'
+	'Automattic\\WooCommerce\\Api\\Infrastructure\\Schema\\AST\\StringValueNode'
 );
diff --git a/plugins/woocommerce/src/Api/README.md b/plugins/woocommerce/src/Api/README.md
index 14a74710990..4ebbad72333 100644
--- a/plugins/woocommerce/src/Api/README.md
+++ b/plugins/woocommerce/src/Api/README.md
@@ -5,3 +5,16 @@ All the code in this directory (`Automattic\WooCommerce\Api` namespace and neste
 Feel free to experiment in testing or staging environments, but **DO NOT** use this code in released extensions or in production environments.

 Also as a reminder, **ALL** the code that's inside the `Automattic\WooCommerce\Internal` namespace and nested namespaces, or that's annotated with `@internal`, is for exclusive usage of WooCommerce core and must **NEVER** be used in extensions or otherwise in production environments.
+
+## Where the autogenerated-callable runtime code lives
+
+The `Infrastructure/` subdirectory holds the classes that the autogenerated GraphQL code emitted by `pnpm build:api` references at runtime:
+
+- `Infrastructure\GraphQLControllerBase`: abstract base extended by each generated `GraphQLController` subclass.
+- `Infrastructure\ResolverHelpers`: exception translation, pagination construction, and authorization helpers called from generated resolvers.
+- `Infrastructure\QueryInfoExtractor`: turns the engine's `ResolveInfo` into the `_query_info` tree resolvers expose to commands.
+- `Infrastructure\MetadataController`: contributes the `_apiMetadata` root query field that every generated schema inherits.
+- `Infrastructure\Schema\*`: the engine-decoupled schema surface (see `Infrastructure/Schema/README.md`); every type/resolver/root-type class in a generated tree imports from here.
+- `Infrastructure\{ClassResolver, Principal, PrincipalResolver}`: convention classes detected at build time and wired into the generated controller.
+
+The public signatures on these classes use only `Api\*` types (and `Schema\*` for any engine-shaped objects), generated trees committed to plugin repos will stay compilable in the event of WooCommerce switching to a different underlying GraphQL engine in the future.
diff --git a/plugins/woocommerce/src/Api/Utils/SchemaHandle.php b/plugins/woocommerce/src/Api/Utils/SchemaHandle.php
index 1a2b7f5e68b..0df691c4b2e 100644
--- a/plugins/woocommerce/src/Api/Utils/SchemaHandle.php
+++ b/plugins/woocommerce/src/Api/Utils/SchemaHandle.php
@@ -22,11 +22,11 @@ use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\Type;
  * via your dual-API `GraphQLController`'s `get_schema()` method:
  *
  *     $schema = wc_get_container()
- *         ->get( \Automattic\WooCommerce\Internal\Api\GraphQLController::class )
+ *         ->get( \Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLController::class )
  *         ->get_schema();
  *
  * WooCommerce plugins implementing their own dual API reach a handle through
- * their own concrete controller the same way.
+ * their own concrete autogenerated controller the same way.
  *
  * The current public surface is the metadata channel: {@see self::get_all_metadata()}
  * returns every metadata row in the schema, {@see self::find_metadata()} applies
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLController.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLController.php
index ad23dca4df8..5661203e13b 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLController.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLController.php
@@ -5,9 +5,9 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated;

-use Automattic\WooCommerce\Internal\Api\Schema\Schema;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Schema;

-class GraphQLController extends \Automattic\WooCommerce\Internal\Api\GraphQLController {
+class GraphQLController extends \Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase {
 	protected function build_schema(): Schema {
 		return new Schema(
 			array(
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateCoupon.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateCoupon.php
index 1a1dbaa3013..bb53630757b 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateCoupon.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateCoupon.php
@@ -6,12 +6,12 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Api\Mutations\Coupons\CreateCoupon as CreateCouponCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Coupon as CouponType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input\CreateCoupon as CreateCouponInput;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CreateCoupon {
 	public static function get_field_definition(): array {
@@ -32,7 +32,7 @@ class CreateCoupon {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( CreateCouponCommand::class );
@@ -42,7 +42,7 @@ class CreateCoupon {
 			$execute_args['input'] = self::convert_create_coupon_input( $args['input'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateProduct.php
index 4eb3c06d60f..684b7ff071f 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/CreateProduct.php
@@ -6,12 +6,12 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Api\Mutations\Products\CreateProduct as CreateProductCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductInterface;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input\CreateProduct as CreateProductInput;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CreateProduct {
 	public static function get_field_definition(): array {
@@ -32,7 +32,7 @@ class CreateProduct {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( CreateProductCommand::class );
@@ -42,7 +42,7 @@ class CreateProduct {
 			$execute_args['input'] = self::convert_create_product_input( $args['input'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteCoupon.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteCoupon.php
index 8895b1f24e9..1c3b1803427 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteCoupon.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteCoupon.php
@@ -6,11 +6,11 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Api\Mutations\Coupons\DeleteCoupon as DeleteCouponCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\DeleteCouponResult as DeleteCouponResultType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class DeleteCoupon {
 	public static function get_field_definition(): array {
@@ -36,7 +36,7 @@ class DeleteCoupon {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( DeleteCouponCommand::class );
@@ -49,7 +49,7 @@ class DeleteCoupon {
 			$execute_args['force'] = $args['force'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteProduct.php
index 0c8c43afd68..c09384b0b80 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/DeleteProduct.php
@@ -6,16 +6,16 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Api\Mutations\Products\DeleteProduct as DeleteProductCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class DeleteProduct {
 	public static function get_field_definition(): array {
 		return array(
 			'type'        => Type::nonNull(
-				new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
 					array(
 						'name'   => 'DeleteProductResult',
 						'fields' => array(
@@ -44,7 +44,7 @@ class DeleteProduct {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( DeleteProductCommand::class );
@@ -57,7 +57,7 @@ class DeleteProduct {
 			$execute_args['force'] = $args['force'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateCoupon.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateCoupon.php
index a01fdff954d..9fcce5708de 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateCoupon.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateCoupon.php
@@ -6,12 +6,12 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Api\Mutations\Coupons\UpdateCoupon as UpdateCouponCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Coupon as CouponType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input\UpdateCoupon as UpdateCouponInput;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class UpdateCoupon {
 	public static function get_field_definition(): array {
@@ -32,7 +32,7 @@ class UpdateCoupon {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( UpdateCouponCommand::class );
@@ -42,7 +42,7 @@ class UpdateCoupon {
 			$execute_args['input'] = self::convert_update_coupon_input( $args['input'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateProduct.php
index 015ffd1c68f..c529ee6a3e9 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLMutations/UpdateProduct.php
@@ -6,12 +6,12 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Api\Mutations\Products\UpdateProduct as UpdateProductCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductInterface;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input\UpdateProduct as UpdateProductInput;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class UpdateProduct {
 	public static function get_field_definition(): array {
@@ -32,7 +32,7 @@ class UpdateProduct {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( UpdateProductCommand::class );
@@ -42,7 +42,7 @@ class UpdateProduct {
 			$execute_args['input'] = self::convert_update_product_input( $args['input'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetCoupon.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetCoupon.php
index 3668feb20be..9bfbe5fc423 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetCoupon.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetCoupon.php
@@ -6,11 +6,11 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Api\Queries\Coupons\GetCoupon as GetCouponCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Coupon as CouponType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class GetCoupon {
 	public static function get_field_definition(): array {
@@ -37,7 +37,7 @@ class GetCoupon {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( GetCouponCommand::class );
@@ -50,7 +50,7 @@ class GetCoupon {
 			$execute_args['code'] = $args['code'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetProduct.php
index 1173d72f47c..fbb32249ada 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/GetProduct.php
@@ -6,11 +6,11 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Api\Queries\Products\GetProduct as GetProductCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class GetProduct {
 	public static function get_field_definition(): array {
@@ -37,17 +37,17 @@ class GetProduct {
 		}
 		$execute_args['_query_info'] = $query_info;

-		if ( ! Utils::authorize_command(
+		if ( ! ResolverHelpers::authorize_command(
 			$command,
 			array(
 				'id'             => $execute_args['id'],
 				'_preauthorized' => self::compute_preauthorized( $context['principal'] ),
 			)
 		) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListCoupons.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListCoupons.php
index 1896ca25d64..c80009d84c4 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListCoupons.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListCoupons.php
@@ -6,12 +6,12 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Api\Queries\Coupons\ListCoupons as ListCouponsCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination\CouponConnection as CouponConnectionType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\CouponStatus as CouponStatusType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ListCoupons {
 	public static function get_field_definition(): array {
@@ -45,7 +45,7 @@ class ListCoupons {
 					'defaultValue' => null,
 				),
 			),
-			'complexity'  => Utils::complexity_from_pagination( ... ),
+			'complexity'  => ResolverHelpers::complexity_from_pagination( ... ),
 			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}
@@ -54,18 +54,18 @@ class ListCoupons {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( ListCouponsCommand::class );

 		$execute_args               = array();
-		$execute_args['pagination'] = Utils::create_pagination_params( $args );
+		$execute_args['pagination'] = ResolverHelpers::create_pagination_params( $args );
 		if ( array_key_exists( 'status', $args ) ) {
 			$execute_args['status'] = $args['status'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListProducts.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListProducts.php
index c80522b35e0..963bfabb1b5 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListProducts.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLQueries/ListProducts.php
@@ -6,14 +6,14 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Api\Queries\Products\ListProducts as ListProductsCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination\ProductConnection as ProductConnectionType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\ProductStatus as ProductStatusType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\StockStatus as StockStatusType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\ProductType as ProductTypeType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ListProducts {
 	public static function get_field_definition(): array {
@@ -62,7 +62,7 @@ class ListProducts {
 					'defaultValue' => null,
 				),
 			),
-			'complexity'  => Utils::complexity_from_pagination( ... ),
+			'complexity'  => ResolverHelpers::complexity_from_pagination( ... ),
 			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}
@@ -71,15 +71,15 @@ class ListProducts {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Api\Infrastructure\ClassResolver::resolve_class( ListProductsCommand::class );

 		$query_info                 = QueryInfoExtractor::extract_from_info( $info, $args );
 		$execute_args               = array();
-		$execute_args['pagination'] = Utils::create_pagination_params( $args );
-		$execute_args['filters']    = Utils::create_input(
+		$execute_args['pagination'] = ResolverHelpers::create_pagination_params( $args );
+		$execute_args['filters']    = ResolverHelpers::create_input(
 			fn() => new \Automattic\WooCommerce\Api\InputTypes\Products\ProductFilterInput(
 				status: $args['status'],
 				stock_status: $args['stock_status'],
@@ -91,7 +91,7 @@ class ListProducts {
 		}
 		$execute_args['_query_info'] = $query_info;

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/CouponStatus.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/CouponStatus.php
index 37f67279a03..69f9754f523 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/CouponStatus.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/CouponStatus.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums;

 use Automattic\WooCommerce\Api\Enums\Coupons\CouponStatus as CouponStatusEnum;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class CouponStatus {
 	private static ?EnumType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/DiscountType.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/DiscountType.php
index be3d856ffb6..7cfb0ed3a61 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/DiscountType.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/DiscountType.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums;

 use Automattic\WooCommerce\Api\Enums\Coupons\DiscountType as DiscountTypeEnum;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class DiscountType {
 	private static ?EnumType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductStatus.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductStatus.php
index c11fe73bee5..544f2320a2c 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductStatus.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductStatus.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums;

 use Automattic\WooCommerce\Api\Enums\Products\ProductStatus as ProductStatusEnum;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class ProductStatus {
 	private static ?EnumType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductType.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductType.php
index b35a5f3941b..ef91dfe58f7 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductType.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/ProductType.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums;

 use Automattic\WooCommerce\Api\Enums\Products\ProductType as ProductTypeEnum;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class ProductType {
 	private static ?EnumType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/StockStatus.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/StockStatus.php
index afb03e84284..cf8915372a9 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/StockStatus.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Enums/StockStatus.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums;

 use Automattic\WooCommerce\Api\Enums\Products\StockStatus as StockStatusEnum;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class StockStatus {
 	private static ?EnumType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateCoupon.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateCoupon.php
index 7fbe29a3953..9328c7c6b14 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateCoupon.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateCoupon.php
@@ -7,8 +7,8 @@ namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\DiscountType as DiscountTypeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\CouponStatus as CouponStatusType;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CreateCoupon {
 	private static ?InputObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateProduct.php
index 68c5c02d659..2827b468ad5 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/CreateProduct.php
@@ -8,8 +8,8 @@ namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\ProductStatus as ProductStatusType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\ProductType as ProductTypeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input\Dimensions as DimensionsInput;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CreateProduct {
 	private static ?InputObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/Dimensions.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/Dimensions.php
index cf1de0d94f1..59a23161b44 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/Dimensions.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/Dimensions.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input;

-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Dimensions {
 	private static ?InputObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/ProductFilter.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/ProductFilter.php
index f67ece29a59..cbfe22bfc6c 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/ProductFilter.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/ProductFilter.php
@@ -7,8 +7,8 @@ namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\ProductStatus as ProductStatusType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\StockStatus as StockStatusType;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductFilter {
 	private static ?InputObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateCoupon.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateCoupon.php
index bf2fa5e16f4..f89460c73ee 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateCoupon.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateCoupon.php
@@ -7,8 +7,8 @@ namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\DiscountType as DiscountTypeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\CouponStatus as CouponStatusType;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class UpdateCoupon {
 	private static ?InputObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateProduct.php
index b07a937ed97..a0f8a8fff6f 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Input/UpdateProduct.php
@@ -8,8 +8,8 @@ namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\ProductStatus as ProductStatusType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\ProductType as ProductTypeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Input\Dimensions as DimensionsInput;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class UpdateProduct {
 	private static ?InputObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/ObjectWithId.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/ObjectWithId.php
index 127fc871431..dbab128006b 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/ObjectWithId.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/ObjectWithId.php
@@ -6,8 +6,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Coupon as CouponType;
-use Automattic\WooCommerce\Internal\Api\Schema\InterfaceType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InterfaceType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ObjectWithId {
 	private static ?InterfaceType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/Product.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/Product.php
index 483dbd6d633..8e76923165a 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/Product.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Interfaces/Product.php
@@ -17,8 +17,8 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Produc
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\ExternalProduct as ExternalProductType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\VariableProduct as VariableProductType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\SimpleProduct as SimpleProductType;
-use Automattic\WooCommerce\Internal\Api\Schema\InterfaceType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InterfaceType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Product {
 	private static ?InterfaceType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/Coupon.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/Coupon.php
index 73b23c597a7..2f081e6fe1c 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/Coupon.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/Coupon.php
@@ -9,8 +9,8 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\Discoun
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Enums\CouponStatus as CouponStatusType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Scalars\DateTime as DateTimeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\ObjectWithId as ObjectWithIdInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Coupon {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/DeleteCouponResult.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/DeleteCouponResult.php
index 694dd79554f..4a9a2da709f 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/DeleteCouponResult.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/DeleteCouponResult.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class DeleteCouponResult {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ExternalProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ExternalProduct.php
index 8b13d74d03d..ae28fa1230c 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ExternalProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ExternalProduct.php
@@ -14,8 +14,8 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Produc
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination\ProductReviewConnection as ProductReviewConnectionType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Scalars\DateTime as DateTimeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ExternalProduct {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductAttribute.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductAttribute.php
index 13bd9982f2e..6b66b67d9b7 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductAttribute.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductAttribute.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductAttribute {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductDimensions.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductDimensions.php
index 882c0f53d33..350df969ab7 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductDimensions.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductDimensions.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductDimensions {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductImage.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductImage.php
index deb803e1fd7..5ace0e2b030 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductImage.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductImage.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductImage {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductReview.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductReview.php
index f08e6333ca8..00189e5dbd8 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductReview.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductReview.php
@@ -6,8 +6,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Scalars\DateTime as DateTimeType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductReview {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductVariation.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductVariation.php
index ab5b0fc94fb..dbfdd841631 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductVariation.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/ProductVariation.php
@@ -15,8 +15,8 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Produc
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination\ProductReviewConnection as ProductReviewConnectionType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Scalars\DateTime as DateTimeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductVariation {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SelectedAttribute.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SelectedAttribute.php
index a2aef1d04f6..93e9b56f70e 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SelectedAttribute.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SelectedAttribute.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class SelectedAttribute {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SimpleProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SimpleProduct.php
index e663e44c065..9a5c11ed5bf 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SimpleProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/SimpleProduct.php
@@ -14,8 +14,8 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Produc
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination\ProductReviewConnection as ProductReviewConnectionType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Scalars\DateTime as DateTimeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class SimpleProduct {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/VariableProduct.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/VariableProduct.php
index 25d362fb225..1c1832b30e3 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/VariableProduct.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Output/VariableProduct.php
@@ -15,10 +15,10 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Produc
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination\ProductReviewConnection as ProductReviewConnectionType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Scalars\DateTime as DateTimeType;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductInterface;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Api\Pagination\Connection;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class VariableProduct {
 	private static ?ObjectType $instance = null;
@@ -58,8 +58,8 @@ class VariableProduct {
 									'description'  => __( 'Return results before this cursor.', 'woocommerce' ),
 								),
 							),
-							'complexity'  => Utils::complexity_from_pagination( ... ),
-							'resolve'     => fn( $parent, array $args ): Connection => Utils::translate_exceptions( fn() => $parent->variations->slice( $args ) ),
+							'complexity'  => ResolverHelpers::complexity_from_pagination( ... ),
+							'resolve'     => fn( $parent, array $args ): Connection => ResolverHelpers::translate_exceptions( fn() => $parent->variations->slice( $args ) ),
 						),
 						'name'              => array(
 							'type'        => Type::nonNull( Type::string() ),
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponConnection.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponConnection.php
index 7d568e75e38..08fbabc9594 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponConnection.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponConnection.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Coupon as CouponType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CouponConnection {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponEdge.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponEdge.php
index 0972ae84fd6..5598e77bf11 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponEdge.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/CouponEdge.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\Coupon as CouponType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CouponEdge {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/PageInfo.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/PageInfo.php
index 20d1e8b594c..a6ca8f7ea47 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/PageInfo.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/PageInfo.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class PageInfo {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductConnection.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductConnection.php
index e286e500ffc..e8b61c2b1ec 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductConnection.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductConnection.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductConnection {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductEdge.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductEdge.php
index c4d4240fd3a..337fd9a5674 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductEdge.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductEdge.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Interfaces\Product as ProductType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductEdge {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewConnection.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewConnection.php
index e9c58f9db01..94c79312124 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewConnection.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewConnection.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\ProductReview as ProductReviewType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductReviewConnection {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewEdge.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewEdge.php
index db026985df7..23a5ecc1bcd 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewEdge.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductReviewEdge.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\ProductReview as ProductReviewType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductReviewEdge {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationConnection.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationConnection.php
index 4ecae409c5d..3a75c4bfe99 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationConnection.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationConnection.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\ProductVariation as ProductVariationType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductVariationConnection {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationEdge.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationEdge.php
index ab412e9c52a..e68e1606a07 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationEdge.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Pagination/ProductVariationEdge.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Output\ProductVariation as ProductVariationType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ProductVariationEdge {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Scalars/DateTime.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Scalars/DateTime.php
index a606c9d60d0..223d835e695 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Scalars/DateTime.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/GraphQLTypes/Scalars/DateTime.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLTypes\Scalars;

 use Automattic\WooCommerce\Api\Scalars\DateTime as DateTimeScalar;
-use Automattic\WooCommerce\Internal\Api\Schema\CustomScalarType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\CustomScalarType;

 class DateTime {
 	private static ?CustomScalarType $instance = null;
@@ -22,18 +22,18 @@ class DateTime {
 						try {
 							return DateTimeScalar::parse( $value );
 						} catch ( \InvalidArgumentException $e ) {
-							throw new \Automattic\WooCommerce\Internal\Api\Schema\Error( $e->getMessage() );
+							throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error( $e->getMessage() );
 						}
 					},
 					'parseLiteral' => function ( $value_node, ?array $variables = null ) {
-						if ( $value_node instanceof \Automattic\WooCommerce\Internal\Api\Schema\AST\StringValueNode ) {
+						if ( $value_node instanceof \Automattic\WooCommerce\Api\Infrastructure\Schema\AST\StringValueNode ) {
 							try {
 								return DateTimeScalar::parse( $value_node->value );
 							} catch ( \InvalidArgumentException $e ) {
-								throw new \Automattic\WooCommerce\Internal\Api\Schema\Error( $e->getMessage() );
+								throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error( $e->getMessage() );
 							}
 						}
-						throw new \Automattic\WooCommerce\Internal\Api\Schema\Error(
+						throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error(
 							'DateTime must be a string, got: ' . $value_node->kind
 						);
 					},
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/RootMutationType.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/RootMutationType.php
index 14d7b282a8a..c2d27b4712e 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/RootMutationType.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/RootMutationType.php
@@ -11,7 +11,7 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations\DeletePro
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations\DeleteCoupon;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations\CreateCoupon;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLMutations\UpdateCoupon;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;

 class RootMutationType {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/RootQueryType.php b/plugins/woocommerce/src/Internal/Api/Autogenerated/RootQueryType.php
index e1f15a579bc..7e2724af54e 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/RootQueryType.php
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/RootQueryType.php
@@ -9,8 +9,8 @@ use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries\ListProduct
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries\GetProduct;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries\GetCoupon;
 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLQueries\ListCoupons;
-use Automattic\WooCommerce\Internal\Api\MetadataController;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\MetadataController;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;

 class RootQueryType {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/api_generation_date.txt b/plugins/woocommerce/src/Internal/Api/Autogenerated/api_generation_date.txt
index c506a3be2b1..70fe96ee5d7 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/api_generation_date.txt
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/api_generation_date.txt
@@ -1 +1 @@
-2026-05-14T09:10:45+00:00
\ No newline at end of file
+2026-05-19T11:37:09+00:00
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Internal/Api/Autogenerated/api_source_hash.txt b/plugins/woocommerce/src/Internal/Api/Autogenerated/api_source_hash.txt
index abfaa569da0..5ee939470e0 100644
--- a/plugins/woocommerce/src/Internal/Api/Autogenerated/api_source_hash.txt
+++ b/plugins/woocommerce/src/Internal/Api/Autogenerated/api_source_hash.txt
@@ -1 +1 @@
-effb4e07b32a1d12897204e7e092d029b51b74f62f150912c7f13ba4aea9d2cf
\ No newline at end of file
+664540c79e947e5fce1e6c925e7f028e7935641fa59ced226b9dba97141d50a6
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Internal/Api/GraphQLEndpointRegistrar.php b/plugins/woocommerce/src/Internal/Api/GraphQLEndpointRegistrar.php
index ff599fb02a0..94e776f16cf 100644
--- a/plugins/woocommerce/src/Internal/Api/GraphQLEndpointRegistrar.php
+++ b/plugins/woocommerce/src/Internal/Api/GraphQLEndpointRegistrar.php
@@ -4,6 +4,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api;

+use Automattic\WooCommerce\Api\Infrastructure\Main;
+
 /**
  * Deferred-registration helper for GraphQL endpoints declared via
  * {@see Main::register_graphql_endpoint()}.
diff --git a/plugins/woocommerce/src/Internal/Api/OpcacheFileExpiry.php b/plugins/woocommerce/src/Internal/Api/OpcacheFileExpiry.php
index d8480a66e05..e115cec8d89 100644
--- a/plugins/woocommerce/src/Internal/Api/OpcacheFileExpiry.php
+++ b/plugins/woocommerce/src/Internal/Api/OpcacheFileExpiry.php
@@ -4,6 +4,9 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api;

+use Automattic\WooCommerce\Api\Infrastructure\Main;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+
 /**
  * Deletes expired OPcache cache files via Action Scheduler.
  */
@@ -36,7 +39,7 @@ class OpcacheFileExpiry {
 			return 0;
 		}

-		$fs = Utils::wp_filesystem();
+		$fs = ResolverHelpers::wp_filesystem();
 		if ( ! $fs ) {
 			return 0;
 		}
diff --git a/plugins/woocommerce/src/Internal/Api/QueryCache.php b/plugins/woocommerce/src/Internal/Api/QueryCache.php
index 8b0f34ed127..2d9d33a40c5 100644
--- a/plugins/woocommerce/src/Internal/Api/QueryCache.php
+++ b/plugins/woocommerce/src/Internal/Api/QueryCache.php
@@ -4,6 +4,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api;

+use Automattic\WooCommerce\Api\Infrastructure\Main;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\DocumentNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\Parser;
 use Automattic\WooCommerce\Vendor\GraphQL\Utils\AST;
@@ -326,7 +328,7 @@ class QueryCache {
 			return false;
 		}

-		$fs = Utils::wp_filesystem();
+		$fs = ResolverHelpers::wp_filesystem();
 		if ( ! $fs || ! $fs->is_writable( $dir ) ) {
 			return false;
 		}
@@ -402,7 +404,7 @@ class QueryCache {
 			return;
 		}

-		$fs = Utils::wp_filesystem();
+		$fs = ResolverHelpers::wp_filesystem();
 		if ( ! $fs || ! $fs->move( $tmp, $path, true ) ) {
 			if ( $fs ) {
 				$fs->delete( $tmp );
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/Error.php b/plugins/woocommerce/src/Internal/Api/Schema/Error.php
deleted file mode 100644
index a1cb4abd6bc..00000000000
--- a/plugins/woocommerce/src/Internal/Api/Schema/Error.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Automattic\WooCommerce\Internal\Api\Schema;
-
-/**
- * Stable subclass of the webonyx Error used by autogenerated resolvers
- * when they need to surface a GraphQL-spec error directly (e.g. the
- * UNAUTHORIZED error an autogenerated authorize()-backed resolver
- * throws before invoking the command).
- *
- * Behaviour is inherited verbatim, including the named `extensions`
- * argument that callers rely on to attach an error code.
- *
- * @internal Reserved for autogenerated resolver code.
- */
-class Error extends \Automattic\WooCommerce\Vendor\GraphQL\Error\Error {
-}
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/ObjectType.php b/plugins/woocommerce/src/Internal/Api/Schema/ObjectType.php
deleted file mode 100644
index f4693581b42..00000000000
--- a/plugins/woocommerce/src/Internal/Api/Schema/ObjectType.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Automattic\WooCommerce\Internal\Api\Schema;
-
-/**
- * Stable subclass of the webonyx ObjectType used by autogenerated output
- * types, pagination types and root Query/Mutation types.
- *
- * The constructor accepts the same associative-array config webonyx
- * documents (keys: `name`, `description`, `fields`, `interfaces`). The
- * `fields` entry is either an array or a callable returning an array of
- * field definitions.
- *
- * The wrapper also recognises a `metadata` key — an associative array
- * mapping metadata `name` => scalar `value` — that ApiBuilder emits for
- * types carrying {@see \Automattic\WooCommerce\Api\Attributes\Metadata}
- * attributes. Webonyx ignores unknown config keys, so this rides through
- * the engine untouched and is surfaced by {@see self::get_metadata()}.
- *
- * @internal Reserved for autogenerated resolver code.
- */
-class ObjectType extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\ObjectType {
-	/**
-	 * Type-level metadata entries declared in the config, keyed by name.
-	 *
-	 * @return array<string, bool|int|float|string|null>
-	 */
-	public function get_metadata(): array {
-		return $this->config['metadata'] ?? array();
-	}
-}
diff --git a/plugins/woocommerce/src/Internal/Api/Schema/Schema.php b/plugins/woocommerce/src/Internal/Api/Schema/Schema.php
deleted file mode 100644
index 66354e51eda..00000000000
--- a/plugins/woocommerce/src/Internal/Api/Schema/Schema.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Automattic\WooCommerce\Internal\Api\Schema;
-
-/**
- * Stable subclass of the webonyx Schema used by autogenerated
- * GraphQLController subclasses.
- *
- * The constructor accepts the same associative-array config that webonyx
- * documents (keys: `query`, `mutation`, `types`, etc.). Extending the
- * webonyx class means webonyx's executor treats an instance of this class
- * identically to its own parent, so no adaptation is needed at runtime.
- *
- * @internal Reserved for autogenerated resolver code.
- */
-class Schema extends \Automattic\WooCommerce\Vendor\GraphQL\Type\Schema {
-}
diff --git a/plugins/woocommerce/src/Internal/Api/Settings.php b/plugins/woocommerce/src/Internal/Api/Settings.php
index 30f4a597089..aa7bb8594de 100644
--- a/plugins/woocommerce/src/Internal/Api/Settings.php
+++ b/plugins/woocommerce/src/Internal/Api/Settings.php
@@ -4,6 +4,9 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Internal\Api;

+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
+use Automattic\WooCommerce\Api\Infrastructure\Main;
+
 /**
  * Settings handling for the GraphQL API.
  *
@@ -68,7 +71,7 @@ class Settings {
 				'desc'     => __( 'Path relative to /wp-json/ where the GraphQL endpoint is exposed. Needs at least two segments (namespace/route), e.g. wc/graphql.', 'woocommerce' ),
 				'desc_tip' => true,
 				'id'       => Main::OPTION_ENDPOINT_URL,
-				'default'  => GraphQLController::DEFAULT_ENDPOINT_URL,
+				'default'  => GraphQLControllerBase::DEFAULT_ENDPOINT_URL,
 				'type'     => 'text',
 			),
 			array(
@@ -82,7 +85,7 @@ class Settings {
 				'title'             => __( 'Maximum query depth', 'woocommerce' ),
 				'desc'              => __( 'Reject queries whose selection nesting exceeds this depth.', 'woocommerce' ),
 				'id'                => Main::OPTION_MAX_QUERY_DEPTH,
-				'default'           => (string) GraphQLController::DEFAULT_MAX_QUERY_DEPTH,
+				'default'           => (string) GraphQLControllerBase::DEFAULT_MAX_QUERY_DEPTH,
 				'type'              => 'number',
 				'custom_attributes' => array( 'min' => '1' ),
 			),
@@ -90,7 +93,7 @@ class Settings {
 				'title'             => __( 'Maximum query complexity', 'woocommerce' ),
 				'desc'              => __( 'Reject queries whose computed complexity score exceeds this value.', 'woocommerce' ),
 				'id'                => Main::OPTION_MAX_QUERY_COMPLEXITY,
-				'default'           => (string) GraphQLController::DEFAULT_MAX_QUERY_COMPLEXITY,
+				'default'           => (string) GraphQLControllerBase::DEFAULT_MAX_QUERY_COMPLEXITY,
 				'type'              => 'number',
 				'custom_attributes' => array( 'min' => '1' ),
 			),
@@ -147,7 +150,7 @@ class Settings {
 	public function sanitize_endpoint_url( $value, array $option, $raw_value ): string {
 		unset( $value, $option );

-		$fallback = (string) get_option( Main::OPTION_ENDPOINT_URL, GraphQLController::DEFAULT_ENDPOINT_URL );
+		$fallback = (string) get_option( Main::OPTION_ENDPOINT_URL, GraphQLControllerBase::DEFAULT_ENDPOINT_URL );

 		if ( ! is_string( $raw_value ) ) {
 			return $fallback;
@@ -167,7 +170,7 @@ class Settings {
 		}

 		foreach ( $parts as $part ) {
-			if ( '' === $part || ! preg_match( GraphQLController::ENDPOINT_URL_SEGMENT_PATTERN, $part ) ) {
+			if ( '' === $part || ! preg_match( GraphQLControllerBase::ENDPOINT_URL_SEGMENT_PATTERN, $part ) ) {
 				\WC_Admin_Settings::add_error(
 					sprintf(
 						/* translators: %s: the invalid path segment */
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/DesignTime/Scripts/StalenessCheckerTest.php b/plugins/woocommerce/tests/php/src/Api/Infrastructure/DesignTime/StalenessCheckerTest.php
similarity index 96%
rename from plugins/woocommerce/tests/php/src/Internal/Api/DesignTime/Scripts/StalenessCheckerTest.php
rename to plugins/woocommerce/tests/php/src/Api/Infrastructure/DesignTime/StalenessCheckerTest.php
index a25497867d5..f1ce3306025 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/DesignTime/Scripts/StalenessCheckerTest.php
+++ b/plugins/woocommerce/tests/php/src/Api/Infrastructure/DesignTime/StalenessCheckerTest.php
@@ -2,9 +2,9 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Tests\Internal\Api\DesignTime\Scripts;
+namespace Automattic\WooCommerce\Tests\Api\Infrastructure\DesignTime;

-use Automattic\WooCommerce\Internal\Api\DesignTime\Scripts\StalenessChecker;
+use Automattic\WooCommerce\Api\Infrastructure\DesignTime\StalenessChecker;
 use WC_Unit_Test_Case;

 /**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/QueryInfoExtractorTest.php b/plugins/woocommerce/tests/php/src/Api/Infrastructure/QueryInfoExtractorTest.php
similarity index 98%
rename from plugins/woocommerce/tests/php/src/Internal/Api/QueryInfoExtractorTest.php
rename to plugins/woocommerce/tests/php/src/Api/Infrastructure/QueryInfoExtractorTest.php
index d226ce135ac..7767d41ed9c 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/QueryInfoExtractorTest.php
+++ b/plugins/woocommerce/tests/php/src/Api/Infrastructure/QueryInfoExtractorTest.php
@@ -8,9 +8,9 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Tests\Internal\Api;
+namespace Automattic\WooCommerce\Tests\Api\Infrastructure;

-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\DocumentNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\FieldNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\FragmentDefinitionNode;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/UtilsTest.php b/plugins/woocommerce/tests/php/src/Api/Infrastructure/ResolverHelpersTest.php
similarity index 78%
rename from plugins/woocommerce/tests/php/src/Internal/Api/UtilsTest.php
rename to plugins/woocommerce/tests/php/src/Api/Infrastructure/ResolverHelpersTest.php
index e301cde4e73..8812c7b02b6 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/UtilsTest.php
+++ b/plugins/woocommerce/tests/php/src/Api/Infrastructure/ResolverHelpersTest.php
@@ -2,25 +2,25 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Tests\Internal\Api;
+namespace Automattic\WooCommerce\Tests\Api\Infrastructure;

 use Automattic\WooCommerce\Api\ApiException;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Api\Pagination\PaginationParams;
-use Automattic\WooCommerce\Internal\Api\Utils;
 use Automattic\WooCommerce\Vendor\GraphQL\Error\Error as GraphQLError;
 use WC_Unit_Test_Case;

 /**
- * Tests for {@see Utils} — the shared helper layer that autogenerated
+ * Tests for {@see ResolverHelpers} — the shared helper layer that autogenerated
  * resolvers route pagination construction and exception translation through.
  */
-class UtilsTest extends WC_Unit_Test_Case {
+class ResolverHelpersTest extends WC_Unit_Test_Case {
 	/**
 	 * @testdox complexity_from_pagination scales the cost by the requested page size.
 	 */
 	public function test_complexity_from_pagination_uses_first_when_provided(): void {
 		// child_complexity 5, first 10 → 10 * (5 + 1) = 60.
-		$this->assertSame( 60, Utils::complexity_from_pagination( 5, array( 'first' => 10 ) ) );
+		$this->assertSame( 60, ResolverHelpers::complexity_from_pagination( 5, array( 'first' => 10 ) ) );
 	}

 	/**
@@ -29,9 +29,9 @@ class UtilsTest extends WC_Unit_Test_Case {
 	public function test_complexity_from_pagination_clamps_invalid_values(): void {
 		$max = PaginationParams::MAX_PAGE_SIZE;

-		$this->assertSame( $max * ( 1 + 1 ), Utils::complexity_from_pagination( 1, array( 'first' => -5 ) ) );
-		$this->assertSame( $max * ( 1 + 1 ), Utils::complexity_from_pagination( 1, array( 'first' => $max + 1 ) ) );
-		$this->assertSame( $max * ( 1 + 1 ), Utils::complexity_from_pagination( 1, array( 'first' => 'not-an-int' ) ) );
+		$this->assertSame( $max * ( 1 + 1 ), ResolverHelpers::complexity_from_pagination( 1, array( 'first' => -5 ) ) );
+		$this->assertSame( $max * ( 1 + 1 ), ResolverHelpers::complexity_from_pagination( 1, array( 'first' => $max + 1 ) ) );
+		$this->assertSame( $max * ( 1 + 1 ), ResolverHelpers::complexity_from_pagination( 1, array( 'first' => 'not-an-int' ) ) );
 	}

 	/**
@@ -39,14 +39,14 @@ class UtilsTest extends WC_Unit_Test_Case {
 	 */
 	public function test_complexity_from_pagination_uses_default_when_omitted(): void {
 		$default = PaginationParams::get_default_page_size();
-		$this->assertSame( $default * ( 2 + 1 ), Utils::complexity_from_pagination( 2, array() ) );
+		$this->assertSame( $default * ( 2 + 1 ), ResolverHelpers::complexity_from_pagination( 2, array() ) );
 	}

 	/**
 	 * @testdox create_pagination_params builds a PaginationParams from raw args.
 	 */
 	public function test_create_pagination_params_builds_a_pagination_params(): void {
-		$params = Utils::create_pagination_params(
+		$params = ResolverHelpers::create_pagination_params(
 			array(
 				'first'  => 5,
 				'after'  => 'cursor-a',
@@ -66,7 +66,7 @@ class UtilsTest extends WC_Unit_Test_Case {
 	public function test_create_pagination_params_translates_invalid_arguments(): void {
 		$this->expectException( GraphQLError::class );
 		try {
-			Utils::create_pagination_params( array( 'first' => -1 ) );
+			ResolverHelpers::create_pagination_params( array( 'first' => -1 ) );
 		} catch ( GraphQLError $e ) {
 			$this->assertSame( 'INVALID_ARGUMENT', $e->getExtensions()['code'] ?? null );
 			throw $e;
@@ -89,7 +89,7 @@ class UtilsTest extends WC_Unit_Test_Case {
 			}
 		};

-		$result = Utils::execute_command(
+		$result = ResolverHelpers::execute_command(
 			$command,
 			array(
 				'a' => 2,
@@ -113,7 +113,7 @@ class UtilsTest extends WC_Unit_Test_Case {
 		};

 		try {
-			Utils::execute_command( $command, array() );
+			ResolverHelpers::execute_command( $command, array() );
 			$this->fail( 'Expected GraphQLError to be thrown.' );
 		} catch ( GraphQLError $e ) {
 			$this->assertSame( 'Coupon not found.', $e->getMessage() );
@@ -137,7 +137,7 @@ class UtilsTest extends WC_Unit_Test_Case {
 		};

 		try {
-			Utils::execute_command( $command, array() );
+			ResolverHelpers::execute_command( $command, array() );
 			$this->fail( 'Expected GraphQLError to be thrown.' );
 		} catch ( GraphQLError $e ) {
 			$this->assertSame( 'NOT_FOUND', $e->getExtensions()['code'] ?? null );
@@ -158,7 +158,7 @@ class UtilsTest extends WC_Unit_Test_Case {
 		};

 		try {
-			Utils::execute_command( $command, array() );
+			ResolverHelpers::execute_command( $command, array() );
 			$this->fail( 'Expected GraphQLError to be thrown.' );
 		} catch ( GraphQLError $e ) {
 			$this->assertSame( 'bad input', $e->getMessage() );
@@ -180,7 +180,7 @@ class UtilsTest extends WC_Unit_Test_Case {
 		};

 		try {
-			Utils::execute_command( $command, array() );
+			ResolverHelpers::execute_command( $command, array() );
 			$this->fail( 'Expected GraphQLError to be thrown.' );
 		} catch ( GraphQLError $e ) {
 			$this->assertSame( 'An unexpected error occurred.', $e->getMessage() );
@@ -204,14 +204,14 @@ class UtilsTest extends WC_Unit_Test_Case {
 			}
 		};

-		$this->assertTrue( Utils::authorize_command( $command, array( 'allow' => true ) ) );
-		$this->assertFalse( Utils::authorize_command( $command, array( 'allow' => false ) ) );
+		$this->assertTrue( ResolverHelpers::authorize_command( $command, array( 'allow' => true ) ) );
+		$this->assertFalse( ResolverHelpers::authorize_command( $command, array( 'allow' => false ) ) );
 	}

 	/**
 	 * @testdox translate_exceptions returns the callable result on success.
 	 */
 	public function test_translate_exceptions_returns_callable_result(): void {
-		$this->assertSame( 'ok', Utils::translate_exceptions( static fn() => 'ok' ) );
+		$this->assertSame( 'ok', ResolverHelpers::translate_exceptions( static fn() => 'ok' ) );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Schema/AliasesTest.php b/plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/AliasesTest.php
similarity index 75%
rename from plugins/woocommerce/tests/php/src/Internal/Api/Schema/AliasesTest.php
rename to plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/AliasesTest.php
index edaae56d4ee..5505b311416 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Schema/AliasesTest.php
+++ b/plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/AliasesTest.php
@@ -2,10 +2,10 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Tests\Internal\Api\Schema;
+namespace Automattic\WooCommerce\Tests\Api\Infrastructure\Schema;

-use Automattic\WooCommerce\Internal\Api\Schema\AST\StringValueNode as AliasedStringValueNode;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo as AliasedResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\AST\StringValueNode as AliasedStringValueNode;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo as AliasedResolveInfo;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\StringValueNode;
 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\ResolveInfo;
 use WC_Unit_Test_Case;
@@ -14,9 +14,9 @@ use WC_Unit_Test_Case;
  * Tests that the `aliases.php` bootstrap registers the surface aliases.
  *
  * These aliases let generated code reference the engine via the
- * Internal\Api\Schema namespace even though webonyx itself constructs the
- * instances. If the alias is broken, every resolver's `resolve()` parameter
- * type-hint check fails at request time.
+ * Api\Infrastructure\Schema namespace even though webonyx itself constructs
+ * the instances. If the alias is broken, every resolver's `resolve()`
+ * parameter type-hint check fails at request time.
  */
 class AliasesTest extends WC_Unit_Test_Case {
 	/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Schema/SubclassesTest.php b/plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/SubclassesTest.php
similarity index 87%
rename from plugins/woocommerce/tests/php/src/Internal/Api/Schema/SubclassesTest.php
rename to plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/SubclassesTest.php
index 8023a432070..6f558135b15 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Schema/SubclassesTest.php
+++ b/plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/SubclassesTest.php
@@ -2,16 +2,16 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Tests\Internal\Api\Schema;
-
-use Automattic\WooCommerce\Internal\Api\Schema\CustomScalarType;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
-use Automattic\WooCommerce\Internal\Api\Schema\Error;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\InterfaceType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Schema;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+namespace Automattic\WooCommerce\Tests\Api\Infrastructure\Schema;
+
+use Automattic\WooCommerce\Api\Infrastructure\Schema\CustomScalarType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Error;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InterfaceType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Schema;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;
 use Automattic\WooCommerce\Vendor\GraphQL\Error\ClientAware;
 use Automattic\WooCommerce\Vendor\GraphQL\Error\Error as WebonyxError;
 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\CustomScalarType as WebonyxCustomScalarType;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Schema/TypeTest.php b/plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/TypeTest.php
similarity index 96%
rename from plugins/woocommerce/tests/php/src/Internal/Api/Schema/TypeTest.php
rename to plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/TypeTest.php
index 629cbcef189..9f5d3e43dc5 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Schema/TypeTest.php
+++ b/plugins/woocommerce/tests/php/src/Api/Infrastructure/Schema/TypeTest.php
@@ -2,9 +2,9 @@

 declare(strict_types=1);

-namespace Automattic\WooCommerce\Tests\Internal\Api\Schema;
+namespace Automattic\WooCommerce\Tests\Api\Infrastructure\Schema;

-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;
 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\BooleanType;
 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\FloatType;
 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\IDType;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AuthorizeTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AuthorizeTest.php
index 6a25adc6d6e..3fc7308094b 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AuthorizeTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AuthorizeTest.php
@@ -27,7 +27,7 @@ class AuthorizeTest extends AutogeneratedTestCase {
 	public function test_authorize_only_query_uses_authorize_method(): void {
 		$source = $this->read_generated_resolver( 'AuthorizeOnlyQuery' );
 		$this->assertStringNotContainsString( 'check_current_user_can', $source );
-		$this->assertStringContainsString( 'Utils::authorize_command', $source );
+		$this->assertStringContainsString( 'ResolverHelpers::authorize_command', $source );

 		wp_set_current_user( 0 );

@@ -72,7 +72,7 @@ class AuthorizeTest extends AutogeneratedTestCase {
 		// The inherited manage_options cap MUST NOT be turned into a check —
 		// authorize() takes over as the sole guard.
 		$this->assertStringNotContainsString( 'check_current_user_can', $source );
-		$this->assertStringContainsString( 'Utils::authorize_command', $source );
+		$this->assertStringContainsString( 'ResolverHelpers::authorize_command', $source );

 		// `editor` has edit_posts but not manage_options. authorize() returns
 		// true → succeeds despite the inherited cap pointing to manage_options.
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AutogeneratedTestCase.php b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AutogeneratedTestCase.php
index 05ad3a56392..116c5fe4b92 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AutogeneratedTestCase.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/AutogeneratedTestCase.php
@@ -10,8 +10,8 @@ use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Store as DummySt
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\RootMutationType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\RootQueryType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\TypeRegistry;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Schema;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Schema;
 use Automattic\WooCommerce\Vendor\GraphQL\GraphQL;
 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\InputObjectType;
 use Automattic\WooCommerce\Vendor\GraphQL\Type\Definition\ListOfType;
@@ -67,7 +67,7 @@ abstract class AutogeneratedTestCase extends WC_Unit_Test_Case {
 	/**
 	 * Execute a GraphQL query against the dummy schema.
 	 *
-	 * Mirrors {@see \Automattic\WooCommerce\Internal\Api\GraphQLController::process_request()}
+	 * Mirrors {@see \Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase::process_request()}
 	 * by populating `contextValue['principal']` with a {@see Principal} wrapping
 	 * {@see \wp_get_current_user()} (anonymous → underlying WP_User has ID=0).
 	 * Tests that need to run as a specific user should call `wp_set_current_user($id)`
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/CustomScalarsTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/CustomScalarsTest.php
index c102237d374..1a0de897294 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/CustomScalarsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/CustomScalarsTest.php
@@ -4,7 +4,7 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api\Autogenerated;

-use Automattic\WooCommerce\Internal\Api\Schema\AST\StringValueNode;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\AST\StringValueNode;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Scalars\DummyDateTime as DummyDateTimeType;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\IntValueNode;

@@ -39,7 +39,7 @@ class CustomScalarsTest extends AutogeneratedTestCase {
 	 * @testdox the custom scalar's parseValue throws a GraphQL Error on malformed input.
 	 */
 	public function test_parse_value_rejects_malformed_input(): void {
-		$this->expectException( \Automattic\WooCommerce\Internal\Api\Schema\Error::class );
+		$this->expectException( \Automattic\WooCommerce\Api\Infrastructure\Schema\Error::class );
 		DummyDateTimeType::get()->parseValue( 'not-a-date' );
 	}

@@ -60,7 +60,7 @@ class CustomScalarsTest extends AutogeneratedTestCase {
 	public function test_parse_literal_rejects_non_string_node(): void {
 		$node = new IntValueNode( array( 'value' => '123' ) );

-		$this->expectException( \Automattic\WooCommerce\Internal\Api\Schema\Error::class );
+		$this->expectException( \Automattic\WooCommerce\Api\Infrastructure\Schema\Error::class );
 		DummyDateTimeType::get()->parseLiteral( $node );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/SchemaShapeTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/SchemaShapeTest.php
index bebb371f48b..99fa9b53bb9 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/SchemaShapeTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Autogenerated/SchemaShapeTest.php
@@ -17,11 +17,11 @@ use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\Gra
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\RootMutationType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\RootQueryType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\TypeRegistry;
-use Automattic\WooCommerce\Internal\Api\Schema\CustomScalarType;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\InterfaceType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\CustomScalarType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InterfaceType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;

 /**
  * Top-level shape assertions on the autogenerated dummy schema. These verify
@@ -30,11 +30,11 @@ use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
  */
 class SchemaShapeTest extends AutogeneratedTestCase {
 	/**
-	 * @testdox the autogenerated GraphQLController extends the abstract base controller.
+	 * @testdox the autogenerated GraphQLControllerBase extends the abstract base controller.
 	 */
 	public function test_generated_controller_extends_base(): void {
 		$this->assertTrue(
-			is_subclass_of( DummyGraphQLController::class, \Automattic\WooCommerce\Internal\Api\GraphQLController::class )
+			is_subclass_of( DummyGraphQLController::class, \Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase::class )
 		);
 	}

diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/ComputePreauthorizedTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/ComputePreauthorizedTest.php
index 537cf2d52ee..2dd9323bfc3 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/ComputePreauthorizedTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/ComputePreauthorizedTest.php
@@ -5,7 +5,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api;

 use Automattic\WooCommerce\Api\Infrastructure\Principal;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Authorization\ComposedAuthorizeQuery;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Inheritance\InheritedCapQuery;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Inheritance\InheritedPublicQuery;
@@ -20,7 +20,7 @@ use WC_Unit_Test_Case;
  * Tests for the dual `compute_preauthorized` paths:
  *
  *   1. The static helper emitted on each autogenerated resolver.
- *   2. The runtime `Utils::compute_preauthorized()` helper that walks the
+ *   2. The runtime `ResolverHelpers::compute_preauthorized()` helper that walks the
  *      command class's attributes via Reflection.
  *
  * Both paths must agree on every command — they implement the same
@@ -97,48 +97,48 @@ class ComputePreauthorizedTest extends WC_Unit_Test_Case {
 	}

 	/**
-	 * @testdox Utils::compute_preauthorized agrees with the autogen helper for inherited capabilities.
+	 * @testdox ResolverHelpers::compute_preauthorized agrees with the autogen helper for inherited capabilities.
 	 */
 	public function test_utils_helper_matches_autogen_for_inherited_cap(): void {
 		foreach ( array( 'administrator', 'subscriber', null ) as $role ) {
 			$principal = $this->principal_with_role( $role );
 			$autogen   = InheritedCapResolver::compute_preauthorized( $principal );
-			$utils     = Utils::compute_preauthorized( InheritedCapQuery::class, $principal );
+			$utils     = ResolverHelpers::compute_preauthorized( InheritedCapQuery::class, $principal );
 			$this->assertSame(
 				$autogen,
 				$utils,
-				'Drift between autogen and Utils for InheritedCapQuery, role: ' . ( $role ?? '<anonymous>' )
+				'Drift between autogen and ResolverHelpers for InheritedCapQuery, role: ' . ( $role ?? '<anonymous>' )
 			);
 		}
 	}

 	/**
-	 * @testdox Utils::compute_preauthorized agrees with the autogen helper for PublicAccess.
+	 * @testdox ResolverHelpers::compute_preauthorized agrees with the autogen helper for PublicAccess.
 	 */
 	public function test_utils_helper_matches_autogen_for_public_access(): void {
 		$anonymous = $this->principal_with_role( null );
-		$this->assertTrue( Utils::compute_preauthorized( InheritedPublicQuery::class, $anonymous ) );
+		$this->assertTrue( ResolverHelpers::compute_preauthorized( InheritedPublicQuery::class, $anonymous ) );
 		$this->assertSame(
 			InheritedPublicResolver::compute_preauthorized( $anonymous ),
-			Utils::compute_preauthorized( InheritedPublicQuery::class, $anonymous )
+			ResolverHelpers::compute_preauthorized( InheritedPublicQuery::class, $anonymous )
 		);
 	}

 	/**
-	 * @testdox Utils::compute_preauthorized agrees with the autogen helper for merged caps.
+	 * @testdox ResolverHelpers::compute_preauthorized agrees with the autogen helper for merged caps.
 	 */
 	public function test_utils_helper_matches_autogen_for_merged_caps(): void {
 		foreach ( array( 'administrator', 'editor', null ) as $role ) {
 			$principal = $this->principal_with_role( $role );
 			$this->assertSame(
 				MergedCapsResolver::compute_preauthorized( $principal ),
-				Utils::compute_preauthorized( MergedCapsQuery::class, $principal )
+				ResolverHelpers::compute_preauthorized( MergedCapsQuery::class, $principal )
 			);
 		}
 	}

 	/**
-	 * @testdox Utils::compute_preauthorized works on a command with both attributes and authorize().
+	 * @testdox ResolverHelpers::compute_preauthorized works on a command with both attributes and authorize().
 	 */
 	public function test_utils_helper_for_command_with_attribute_and_authorize_method(): void {
 		// ComposedAuthorizeQuery has both an attribute AND an authorize() method.
@@ -148,22 +148,22 @@ class ComputePreauthorizedTest extends WC_Unit_Test_Case {
 		$this->assertTrue( ComposedAuthorizeResolver::compute_preauthorized( $admin ) );
 		$this->assertSame(
 			ComposedAuthorizeResolver::compute_preauthorized( $admin ),
-			Utils::compute_preauthorized( ComposedAuthorizeQuery::class, $admin )
+			ResolverHelpers::compute_preauthorized( ComposedAuthorizeQuery::class, $admin )
 		);

 		$anonymous = $this->principal_with_role( null );
 		$this->assertFalse( ComposedAuthorizeResolver::compute_preauthorized( $anonymous ) );
 		$this->assertSame(
 			ComposedAuthorizeResolver::compute_preauthorized( $anonymous ),
-			Utils::compute_preauthorized( ComposedAuthorizeQuery::class, $anonymous )
+			ResolverHelpers::compute_preauthorized( ComposedAuthorizeQuery::class, $anonymous )
 		);
 	}

 	/**
-	 * @testdox Utils::compute_preauthorized rejects an unknown class.
+	 * @testdox ResolverHelpers::compute_preauthorized rejects an unknown class.
 	 */
 	public function test_utils_helper_rejects_unknown_class(): void {
 		$this->expectException( \InvalidArgumentException::class );
-		Utils::compute_preauthorized( '\\Definitely\\Not\\A\\Class', $this->principal_with_role( null ) );
+		ResolverHelpers::compute_preauthorized( '\\Definitely\\Not\\A\\Class', $this->principal_with_role( null ) );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLController.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLController.php
index 97849dd4440..6ee6c8305cf 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLController.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLController.php
@@ -5,9 +5,9 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated;

-use Automattic\WooCommerce\Internal\Api\Schema\Schema;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Schema;

-class GraphQLController extends \Automattic\WooCommerce\Internal\Api\GraphQLController {
+class GraphQLController extends \Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase {
 	protected function build_schema(): Schema {
 		return new Schema(
 			array(
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/CreateWidget.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/CreateWidget.php
index 48625783c9e..ea1b75bc835 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/CreateWidget.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/CreateWidget.php
@@ -6,30 +6,30 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Mutations\CreateWidget as CreateWidgetCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\Widget as WidgetType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Input\CreateWidget as CreateWidgetInput;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CreateWidget {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(WidgetType::get()),
+			'type'        => Type::nonNull( WidgetType::get() ),
 			'description' => __( 'Create a new widget', 'woocommerce' ),
-			'args' => array(
-				'input' => array(
-					'type' => Type::nonNull(CreateWidgetInput::get()),
-						'description' => __( 'The data for the new widget', 'woocommerce' ),
-						),
+			'args'        => array(
+				'input'          => array(
+					'type'        => Type::nonNull( CreateWidgetInput::get() ),
+					'description' => __( 'The data for the new widget', 'woocommerce' ),
+				),
 				'related_inputs' => array(
-					'type' => Type::listOf(Type::nonNull(CreateWidgetInput::get())),
-						'description' => __( 'Related widget inputs for array input generation coverage', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
+					'type'         => Type::listOf( Type::nonNull( CreateWidgetInput::get() ) ),
+					'description'  => __( 'Related widget inputs for array input generation coverage', 'woocommerce' ),
+					'defaultValue' => null,
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -37,7 +37,7 @@ class CreateWidget {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( CreateWidgetCommand::class );
@@ -50,7 +50,7 @@ class CreateWidget {
 			$execute_args['related_inputs'] = $args['related_inputs'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
@@ -67,15 +67,15 @@ class CreateWidget {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}

 	private static function convert_create_widget_input( array $data ): \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\InputTypes\CreateWidgetInput {
 		$input = new \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\InputTypes\CreateWidgetInput();

-			if ( array_key_exists( 'label', $data ) ) {
+		if ( array_key_exists( 'label', $data ) ) {
 			$input->mark_provided( 'label' );
-					$input->label = $data['label'];
+				$input->label = $data['label'];
 		}
 		if ( array_key_exists( 'weight', $data ) ) {
 			$input->mark_provided( 'weight' );
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/DeleteWidget.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/DeleteWidget.php
index efe9ae96bac..d7bb11c41c5 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/DeleteWidget.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/DeleteWidget.php
@@ -6,29 +6,29 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Mutations\DeleteWidget as DeleteWidgetCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\OperationResult as OperationResultType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class DeleteWidget {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(OperationResultType::get()),
+			'type'        => Type::nonNull( OperationResultType::get() ),
 			'description' => __( 'Delete a widget', 'woocommerce' ),
-			'args' => array(
-				'id' => array(
-					'type' => Type::nonNull(Type::int()),
-						'description' => __( 'The widget id to delete', 'woocommerce' ),
-						),
+			'args'        => array(
+				'id'    => array(
+					'type'        => Type::nonNull( Type::int() ),
+					'description' => __( 'The widget id to delete', 'woocommerce' ),
+				),
 				'force' => array(
-					'type' => Type::nonNull(Type::boolean()),
-						'description' => __( 'When true, ignore \"not found\" errors', 'woocommerce' ),
-						'defaultValue' => false,
-					),
+					'type'         => Type::nonNull( Type::boolean() ),
+					'description'  => __( 'When true, ignore \"not found\" errors', 'woocommerce' ),
+					'defaultValue' => false,
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -36,7 +36,7 @@ class DeleteWidget {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( DeleteWidgetCommand::class );
@@ -49,7 +49,7 @@ class DeleteWidget {
 			$execute_args['force'] = $args['force'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
@@ -66,6 +66,6 @@ class DeleteWidget {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/Increment.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/Increment.php
index bd37ee56f13..a8d7f501ff6 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/Increment.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLMutations/Increment.php
@@ -6,33 +6,37 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLMutations;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Mutations\Increment as IncrementCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Increment {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'IncrementResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::int()) ),
-				),
-			))),
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'IncrementResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::int() ) ),
+						),
+					)
+				)
+			),
 			'description' => __( 'Increment a value by an optional amount', 'woocommerce' ),
-			'args' => array(
+			'args'        => array(
 				'value' => array(
-					'type' => Type::nonNull(Type::int()),
-						'description' => __( 'The starting value', 'woocommerce' ),
-						),
-				'by' => array(
-					'type' => Type::nonNull(Type::int()),
-						'description' => __( 'How much to add', 'woocommerce' ),
-						'defaultValue' => 1,
-					),
+					'type'        => Type::nonNull( Type::int() ),
+					'description' => __( 'The starting value', 'woocommerce' ),
+				),
+				'by'    => array(
+					'type'         => Type::nonNull( Type::int() ),
+					'description'  => __( 'How much to add', 'woocommerce' ),
+					'defaultValue' => 1,
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -47,7 +51,7 @@ class Increment {
 			$execute_args['by'] = $args['by'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeOnlyQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeOnlyQuery.php
index adf93ca4d60..1504871e30b 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeOnlyQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeOnlyQuery.php
@@ -6,27 +6,31 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Authorization\AuthorizeOnlyQuery as AuthorizeOnlyQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class AuthorizeOnlyQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'AuthorizeOnlyQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'AuthorizeOnlyQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
+			),
 			'description' => __( 'Authorization decided solely by authorize()', 'woocommerce' ),
-			'args' => array(
+			'args'        => array(
 				'allow' => array(
-					'type' => Type::nonNull(Type::boolean()),
-							),
+					'type' => Type::nonNull( Type::boolean() ),
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -38,13 +42,16 @@ class AuthorizeOnlyQuery {
 			$execute_args['allow'] = $args['allow'];
 		}

-		if ( ! Utils::authorize_command( $command, array(
-			'allow' => $execute_args['allow'],
-		) ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+		if ( ! ResolverHelpers::authorize_command(
+			$command,
+			array(
+				'allow' => $execute_args['allow'],
+			)
+		) ) {
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeThrowsQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeThrowsQuery.php
index cad9f89e4aa..b8780269009 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeThrowsQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/AuthorizeThrowsQuery.php
@@ -6,28 +6,32 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Authorization\AuthorizeThrowsQuery as AuthorizeThrowsQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class AuthorizeThrowsQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'AuthorizeThrowsQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'AuthorizeThrowsQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
+			),
 			'description' => __( 'authorize() throws to verify exception translation', 'woocommerce' ),
-			'args' => array(
+			'args'        => array(
 				'kind' => array(
-					'type' => Type::nonNull(Type::string()),
-						'description' => __( 'Which exception class authorize() should raise.', 'woocommerce' ),
-						),
+					'type'        => Type::nonNull( Type::string() ),
+					'description' => __( 'Which exception class authorize() should raise.', 'woocommerce' ),
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -39,13 +43,16 @@ class AuthorizeThrowsQuery {
 			$execute_args['kind'] = $args['kind'];
 		}

-		if ( ! Utils::authorize_command( $command, array(
-			'kind' => $execute_args['kind'],
-		) ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+		if ( ! ResolverHelpers::authorize_command(
+			$command,
+			array(
+				'kind' => $execute_args['kind'],
+			)
+		) ) {
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ComposedAuthorizeQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ComposedAuthorizeQuery.php
index 45b21f78147..f90591de93e 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ComposedAuthorizeQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ComposedAuthorizeQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Authorization\ComposedAuthorizeQuery as ComposedAuthorizeQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ComposedAuthorizeQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'ComposedAuthorizeQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'Composes #[RequiredCapability] with authorize() via $_preauthorized', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'ComposedAuthorizeQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'Composes #[RequiredCapability] with authorize() via $_preauthorized', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -32,13 +35,16 @@ class ComposedAuthorizeQuery {

 		$execute_args = array();

-		if ( ! Utils::authorize_command( $command, array(
-			'_preauthorized' => self::compute_preauthorized( $context['principal'] ),
-		) ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+		if ( ! ResolverHelpers::authorize_command(
+			$command,
+			array(
+				'_preauthorized' => self::compute_preauthorized( $context['principal'] ),
+			)
+		) ) {
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
@@ -55,6 +61,6 @@ class ComposedAuthorizeQuery {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/FailingQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/FailingQuery.php
index cb7dec96f50..d803d5be750 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/FailingQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/FailingQuery.php
@@ -6,29 +6,33 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\FailingQuery as FailingQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class FailingQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'FailingQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'FailingQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
+			),
 			'description' => __( 'Always throws an exception', 'woocommerce' ),
-			'args' => array(
+			'args'        => array(
 				'kind' => array(
-					'type' => Type::nonNull(Type::string()),
-						'description' => __( 'What kind of failure to raise', 'woocommerce' ),
-						'defaultValue' => 'invalid_argument',
-					),
+					'type'         => Type::nonNull( Type::string() ),
+					'description'  => __( 'What kind of failure to raise', 'woocommerce' ),
+					'defaultValue' => 'invalid_argument',
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -40,7 +44,7 @@ class FailingQuery {
 			$execute_args['kind'] = $args['kind'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetGreeting.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetGreeting.php
index 2f872f71761..a4fdd7e9147 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetGreeting.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetGreeting.php
@@ -6,29 +6,33 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\GetGreeting as GetGreetingCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class GetGreeting {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'GetGreetingResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'GetGreetingResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
+			),
 			'description' => __( 'Build a greeting', 'woocommerce' ),
-			'args' => array(
+			'args'        => array(
 				'name' => array(
-					'type' => Type::string(),
-						'description' => __( 'Who to greet (defaults to \"world\")', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
+					'type'         => Type::string(),
+					'description'  => __( 'Who to greet (defaults to \"world\")', 'woocommerce' ),
+					'defaultValue' => null,
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -40,7 +44,7 @@ class GetGreeting {
 			$execute_args['name'] = $args['name'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetIdentifiable.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetIdentifiable.php
index ad7790e4318..42bc6b4aa35 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetIdentifiable.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetIdentifiable.php
@@ -6,24 +6,24 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\GetIdentifiable as GetIdentifiableCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Interfaces\Named as NamedInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class GetIdentifiable {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(NamedInterface::get()),
+			'type'        => Type::nonNull( NamedInterface::get() ),
 			'description' => __( 'Return either a Widget or a Gadget, both of which implement Named', 'woocommerce' ),
-			'args' => array(
+			'args'        => array(
 				'kind' => array(
-					'type' => Type::nonNull(Type::string()),
-						'description' => __( 'Which kind of object to return', 'woocommerce' ),
-						),
+					'type'        => Type::nonNull( Type::string() ),
+					'description' => __( 'Which kind of object to return', 'woocommerce' ),
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -35,7 +35,7 @@ class GetIdentifiable {
 			$execute_args['kind'] = $args['kind'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetWidget.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetWidget.php
index 429b3dcba03..29bd884abae 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetWidget.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/GetWidget.php
@@ -6,24 +6,24 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\GetWidget as GetWidgetCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\Widget as WidgetType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class GetWidget {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => WidgetType::get(),
+			'type'        => WidgetType::get(),
 			'description' => __( 'Fetch a single widget by ID', 'woocommerce' ),
-			'args' => array(
+			'args'        => array(
 				'id' => array(
-					'type' => Type::nonNull(Type::int()),
-						'description' => __( 'The ID of the widget to fetch', 'woocommerce' ),
-						),
+					'type'        => Type::nonNull( Type::int() ),
+					'description' => __( 'The ID of the widget to fetch', 'woocommerce' ),
+				),
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -31,7 +31,7 @@ class GetWidget {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( GetWidgetCommand::class );
@@ -41,7 +41,7 @@ class GetWidget {
 			$execute_args['id'] = $args['id'];
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
@@ -58,6 +58,6 @@ class GetWidget {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/IgnoredAuthorizeQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/IgnoredAuthorizeQuery.php
index cc3e49a8910..68b176032a9 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/IgnoredAuthorizeQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/IgnoredAuthorizeQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Authorization\IgnoredAuthorizeQuery as IgnoredAuthorizeQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class IgnoredAuthorizeQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'IgnoredAuthorizeQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'authorize() with #[Ignore] is skipped; the cap check applies', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'IgnoredAuthorizeQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'authorize() with #[Ignore] is skipped; the cap check applies', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -31,14 +34,14 @@ class IgnoredAuthorizeQuery {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( IgnoredAuthorizeQueryCommand::class );

 		$execute_args = array();

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
@@ -55,6 +58,6 @@ class IgnoredAuthorizeQuery {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedCapQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedCapQuery.php
index 0b3126907da..6db04a5175b 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedCapQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedCapQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Inheritance\InheritedCapQuery as InheritedCapQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class InheritedCapQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'InheritedCapQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'Inherits manage_options from its abstract parent', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'InheritedCapQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'Inherits manage_options from its abstract parent', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -31,14 +34,14 @@ class InheritedCapQuery {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( InheritedCapQueryCommand::class );

 		$execute_args = array();

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
@@ -55,6 +58,6 @@ class InheritedCapQuery {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedFromInterfaceQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedFromInterfaceQuery.php
index 0c773dc536c..e24513f1b1c 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedFromInterfaceQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedFromInterfaceQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Inheritance\InheritedFromInterfaceQuery as InheritedFromInterfaceQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class InheritedFromInterfaceQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'InheritedFromInterfaceQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'Inherits manage_options from a PHP interface', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'InheritedFromInterfaceQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'Inherits manage_options from a PHP interface', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -31,14 +34,14 @@ class InheritedFromInterfaceQuery {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( InheritedFromInterfaceQueryCommand::class );

 		$execute_args = array();

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
@@ -55,6 +58,6 @@ class InheritedFromInterfaceQuery {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedPublicQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedPublicQuery.php
index 5f340e690a3..e342897a22f 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedPublicQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/InheritedPublicQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Inheritance\InheritedPublicQuery as InheritedPublicQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class InheritedPublicQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'InheritedPublicQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'Inherits PublicAccess via a trait', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'InheritedPublicQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'Inherits PublicAccess via a trait', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -32,7 +35,7 @@ class InheritedPublicQuery {

 		$execute_args = array();

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ListWidgets.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ListWidgets.php
index 1dc13852a1f..b518a932fdc 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ListWidgets.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/ListWidgets.php
@@ -6,58 +6,58 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\ListWidgets as ListWidgetsCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Pagination\WidgetConnection as WidgetConnectionType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Enums\Color as ColorType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Enums\Priority as PriorityType;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class ListWidgets {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(WidgetConnectionType::get()),
+			'type'        => Type::nonNull( WidgetConnectionType::get() ),
 			'description' => __( 'List widgets with cursor-based pagination', 'woocommerce' ),
-			'args' => array(
-				'first' => array(
-					'type' => Type::int(),
-						'description' => __( 'Return the first N results. Must be between 0 and 100.', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
-				'last' => array(
-					'type' => Type::int(),
-						'description' => __( 'Return the last N results. Must be between 0 and 100.', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
-				'after' => array(
-					'type' => Type::string(),
-						'description' => __( 'Return results after this cursor.', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
-				'before' => array(
-					'type' => Type::string(),
-						'description' => __( 'Return results before this cursor.', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
-				'search' => array(
-					'type' => Type::string(),
-						'description' => __( 'A free-text search term', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
-				'color' => array(
-					'type' => ColorType::get(),
-						'description' => __( 'Filter widgets by color', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
+			'args'        => array(
+				'first'        => array(
+					'type'         => Type::int(),
+					'description'  => __( 'Return the first N results. Must be between 0 and 100.', 'woocommerce' ),
+					'defaultValue' => null,
+				),
+				'last'         => array(
+					'type'         => Type::int(),
+					'description'  => __( 'Return the last N results. Must be between 0 and 100.', 'woocommerce' ),
+					'defaultValue' => null,
+				),
+				'after'        => array(
+					'type'         => Type::string(),
+					'description'  => __( 'Return results after this cursor.', 'woocommerce' ),
+					'defaultValue' => null,
+				),
+				'before'       => array(
+					'type'         => Type::string(),
+					'description'  => __( 'Return results before this cursor.', 'woocommerce' ),
+					'defaultValue' => null,
+				),
+				'search'       => array(
+					'type'         => Type::string(),
+					'description'  => __( 'A free-text search term', 'woocommerce' ),
+					'defaultValue' => null,
+				),
+				'color'        => array(
+					'type'         => ColorType::get(),
+					'description'  => __( 'Filter widgets by color', 'woocommerce' ),
+					'defaultValue' => null,
+				),
 				'min_priority' => array(
-					'type' => PriorityType::get(),
-						'description' => __( 'A second filter applied after the unrolled ones', 'woocommerce' ),
-						'defaultValue' => NULL,
-					),
+					'type'         => PriorityType::get(),
+					'description'  => __( 'A second filter applied after the unrolled ones', 'woocommerce' ),
+					'defaultValue' => null,
+				),
 			),
-			'complexity' => Utils::complexity_from_pagination(...),
-			'resolve' => array( self::class, 'resolve' ),
+			'complexity'  => ResolverHelpers::complexity_from_pagination( ... ),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -65,17 +65,17 @@ class ListWidgets {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( ListWidgetsCommand::class );

-		$query_info = QueryInfoExtractor::extract_from_info( $info, $args );
-		$execute_args = array();
-		$execute_args['pagination'] = Utils::create_pagination_params( $args );
-		$execute_args['filters'] = Utils::create_input(
+		$query_info                 = QueryInfoExtractor::extract_from_info( $info, $args );
+		$execute_args               = array();
+		$execute_args['pagination'] = ResolverHelpers::create_pagination_params( $args );
+		$execute_args['filters']    = ResolverHelpers::create_input(
 			fn() => new \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\InputTypes\WidgetFilterInput(
-				search: $args['search'] ?? NULL,
+				search: $args['search'] ?? null,
 				color: $args['color'],
 			)
 		);
@@ -84,7 +84,7 @@ class ListWidgets {
 		}
 		$execute_args['_query_info'] = $query_info;

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return $result;
 	}
@@ -101,6 +101,6 @@ class ListWidgets {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal ) && ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('edit_posts') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal ) && ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'edit_posts' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/MergedCapsQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/MergedCapsQuery.php
index a1f9d7933ac..450a8d511b9 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/MergedCapsQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/MergedCapsQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Inheritance\MergedCapsQuery as MergedCapsQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class MergedCapsQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'MergedCapsQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'Merges caps from a parent class and a trait', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'MergedCapsQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'Merges caps from a parent class and a trait', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -31,14 +34,14 @@ class MergedCapsQuery {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( MergedCapsQueryCommand::class );

 		$execute_args = array();

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
@@ -55,6 +58,6 @@ class MergedCapsQuery {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal ) && ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('edit_posts') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal ) && ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'edit_posts' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenAuthorizeQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenAuthorizeQuery.php
index dcaa3c43b3c..0d7fdd15935 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenAuthorizeQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenAuthorizeQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Authorization\OverriddenAuthorizeQuery as OverriddenAuthorizeQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class OverriddenAuthorizeQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'OverriddenAuthorizeQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'authorize() supersedes the cap inherited from the parent', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'OverriddenAuthorizeQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'authorize() supersedes the cap inherited from the parent', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -32,12 +35,14 @@ class OverriddenAuthorizeQuery {

 		$execute_args = array();

-		if ( ! Utils::authorize_command( $command, array(
-		) ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+		if ( ! ResolverHelpers::authorize_command(
+			$command,
+			array()
+		) ) {
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
@@ -54,6 +59,6 @@ class OverriddenAuthorizeQuery {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_options') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_options' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenCapQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenCapQuery.php
index 667871568ad..33ad3b802b9 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenCapQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/OverriddenCapQuery.php
@@ -6,24 +6,27 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Inheritance\OverriddenCapQuery as OverriddenCapQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class OverriddenCapQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'OverriddenCapQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'Overrides the inherited manage_options with manage_categories', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'OverriddenCapQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'Overrides the inherited manage_options with manage_categories', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

@@ -31,14 +34,14 @@ class OverriddenCapQuery {
 		// Standalone authorization gate: no authorize() method on the command,
 		// so the autodiscovered authorization attributes are the sole guard.
 		if ( ! self::compute_preauthorized( $context['principal'] ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( OverriddenCapQueryCommand::class );

 		$execute_args = array();

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
@@ -55,6 +58,6 @@ class OverriddenCapQuery {
 	 * method should be consulted instead).
 	 */
 	public static function compute_preauthorized( \Automattic\WooCommerce\Api\Infrastructure\Principal $principal ): bool {
-		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability('manage_categories') )->authorize( $principal );
+		return ( new \Automattic\WooCommerce\Api\Attributes\RequiredCapability( 'manage_categories' ) )->authorize( $principal );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/PrincipalAwareQuery.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/PrincipalAwareQuery.php
index c1907850d51..71a443d2657 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/PrincipalAwareQuery.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLQueries/PrincipalAwareQuery.php
@@ -6,40 +6,46 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Queries\Authorization\PrincipalAwareQuery as PrincipalAwareQueryCommand;
-use Automattic\WooCommerce\Internal\Api\QueryInfoExtractor;
-use Automattic\WooCommerce\Internal\Api\Utils;
-use Automattic\WooCommerce\Internal\Api\Schema\ResolveInfo;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\QueryInfoExtractor;
+use Automattic\WooCommerce\Api\Infrastructure\ResolverHelpers;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ResolveInfo;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class PrincipalAwareQuery {
 	public static function get_field_definition(): array {
 		return array(
-			'type' => Type::nonNull(new \Automattic\WooCommerce\Internal\Api\Schema\ObjectType(array(
-				'name' => 'PrincipalAwareQueryResult',
-				'fields' => array(
-					'result' => array( 'type' => Type::nonNull(Type::string()) ),
-				),
-			))),
-			'description' => __( 'Echoes the principal user_login (or \"anonymous\").', 'woocommerce' ),
-			'args' => array(
+			'type'        => Type::nonNull(
+				new \Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType(
+					array(
+						'name'   => 'PrincipalAwareQueryResult',
+						'fields' => array(
+							'result' => array( 'type' => Type::nonNull( Type::string() ) ),
+						),
+					)
+				)
 			),
-			'resolve' => array( self::class, 'resolve' ),
+			'description' => __( 'Echoes the principal user_login (or \"anonymous\").', 'woocommerce' ),
+			'args'        => array(),
+			'resolve'     => array( self::class, 'resolve' ),
 		);
 	}

 	public static function resolve( mixed $root, array $args, mixed $context, ResolveInfo $info ): mixed {
 		$command = \Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver::resolve_class( PrincipalAwareQueryCommand::class );

-		$execute_args = array();
+		$execute_args               = array();
 		$execute_args['_principal'] = $context['principal'];

-		if ( ! Utils::authorize_command( $command, array(
-			'_principal' => $context['principal'],
-		) ) ) {
-			throw Utils::build_authorization_error( $context['principal'] );
+		if ( ! ResolverHelpers::authorize_command(
+			$command,
+			array(
+				'_principal' => $context['principal'],
+			)
+		) ) {
+			throw ResolverHelpers::build_authorization_error( $context['principal'] );
 		}

-		$result = Utils::execute_command( $command, $execute_args );
+		$result = ResolverHelpers::execute_command( $command, $execute_args );

 		return array( 'result' => $result );
 	}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Color.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Color.php
index a09d7074537..34c14dc34fe 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Color.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Color.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Enums;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Enums\Color as ColorEnum;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class Color {
 	private static ?EnumType $instance = null;
@@ -15,20 +15,20 @@ class Color {
 		if ( null === self::$instance ) {
 			self::$instance = new EnumType(
 				array(
-					'name' => 'Color',
+					'name'        => 'Color',
 					'description' => __( 'A simple color palette', 'woocommerce' ),
-					'values' => array(
-						'RED' => array(
-							'value' => ColorEnum::Red,
-								'description' => __( 'Red', 'woocommerce' ),
-								),
+					'values'      => array(
+						'RED'   => array(
+							'value'       => ColorEnum::Red,
+							'description' => __( 'Red', 'woocommerce' ),
+						),
 						'GREEN' => array(
-							'value' => ColorEnum::Green,
-								'description' => __( 'Green', 'woocommerce' ),
-								),
-						'BLUE' => array(
+							'value'       => ColorEnum::Green,
+							'description' => __( 'Green', 'woocommerce' ),
+						),
+						'BLUE'  => array(
 							'value' => ColorEnum::Blue,
-									),
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Priority.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Priority.php
index c2062fd6ce6..9214a2d596d 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Priority.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Enums/Priority.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Enums;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Enums\Priority as PriorityEnum;
-use Automattic\WooCommerce\Internal\Api\Schema\EnumType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\EnumType;

 class Priority {
 	private static ?EnumType $instance = null;
@@ -15,21 +15,21 @@ class Priority {
 		if ( null === self::$instance ) {
 			self::$instance = new EnumType(
 				array(
-					'name' => 'TaskPriority',
+					'name'        => 'TaskPriority',
 					'description' => __( 'Priority level for a task', 'woocommerce' ),
-					'values' => array(
-						'LOW' => array(
-							'value' => PriorityEnum::Low,
-								'description' => __( 'Low priority', 'woocommerce' ),
-								),
+					'values'      => array(
+						'LOW'             => array(
+							'value'       => PriorityEnum::Low,
+							'description' => __( 'Low priority', 'woocommerce' ),
+						),
 						'NORMAL_PRIORITY' => array(
 							'value' => PriorityEnum::Normal,
-									),
-						'HIGH' => array(
-							'value' => PriorityEnum::High,
-								'description' => __( 'High priority', 'woocommerce' ),
-								'deprecationReason' => 'Use NORMAL_PRIORITY instead.',
-							),
+						),
+						'HIGH'            => array(
+							'value'             => PriorityEnum::High,
+							'description'       => __( 'High priority', 'woocommerce' ),
+							'deprecationReason' => 'Use NORMAL_PRIORITY instead.',
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/CreateWidget.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/CreateWidget.php
index eee91f9f3f6..0e7168cd0c0 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/CreateWidget.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/CreateWidget.php
@@ -7,8 +7,8 @@ namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerat

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Enums\Color as ColorType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Scalars\DummyDateTime as DummyDateTimeType;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class CreateWidget {
 	private static ?InputObjectType $instance = null;
@@ -17,29 +17,29 @@ class CreateWidget {
 		if ( null === self::$instance ) {
 			self::$instance = new InputObjectType(
 				array(
-					'name' => 'CreateWidgetInput',
+					'name'        => 'CreateWidgetInput',
 					'description' => __( 'Data needed to create a new widget', 'woocommerce' ),
-					'fields' => fn() => array(
-						'label' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'The widget label', 'woocommerce' ),
-							),
-						'weight' => array(
-							'type' => Type::int(),
-								'description' => __( 'Optional weight in grams', 'woocommerce' ),
-							),
-						'color' => array(
-							'type' => Type::nonNull(ColorType::get()),
-								'description' => __( 'The widget color', 'woocommerce' ),
-							),
-						'tag_ids' => array(
-							'type' => Type::listOf(Type::nonNull(Type::int())),
-								'description' => __( 'Tag IDs to attach to the widget', 'woocommerce' ),
-							),
+					'fields'      => fn() => array(
+						'label'      => array(
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'The widget label', 'woocommerce' ),
+						),
+						'weight'     => array(
+							'type'        => Type::int(),
+							'description' => __( 'Optional weight in grams', 'woocommerce' ),
+						),
+						'color'      => array(
+							'type'        => Type::nonNull( ColorType::get() ),
+							'description' => __( 'The widget color', 'woocommerce' ),
+						),
+						'tag_ids'    => array(
+							'type'        => Type::listOf( Type::nonNull( Type::int() ) ),
+							'description' => __( 'Tag IDs to attach to the widget', 'woocommerce' ),
+						),
 						'expires_at' => array(
-							'type' => DummyDateTimeType::get(),
-								'description' => __( 'When the widget should expire', 'woocommerce' ),
-							),
+							'type'        => DummyDateTimeType::get(),
+							'description' => __( 'When the widget should expire', 'woocommerce' ),
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/WidgetFilter.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/WidgetFilter.php
index 5fcae20c1ef..d9c7cd7f71c 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/WidgetFilter.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Input/WidgetFilter.php
@@ -6,8 +6,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Input;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Enums\Color as ColorType;
-use Automattic\WooCommerce\Internal\Api\Schema\InputObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InputObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class WidgetFilter {
 	private static ?InputObjectType $instance = null;
@@ -16,17 +16,17 @@ class WidgetFilter {
 		if ( null === self::$instance ) {
 			self::$instance = new InputObjectType(
 				array(
-					'name' => 'WidgetFilterArgs',
+					'name'        => 'WidgetFilterArgs',
 					'description' => __( 'Filters applied to a widget listing', 'woocommerce' ),
-					'fields' => fn() => array(
+					'fields'      => fn() => array(
 						'search' => array(
-							'type' => Type::string(),
-								'description' => __( 'A free-text search term', 'woocommerce' ),
-							),
-						'color' => array(
-							'type' => ColorType::get(),
-								'description' => __( 'Filter widgets by color', 'woocommerce' ),
-							),
+							'type'        => Type::string(),
+							'description' => __( 'A free-text search term', 'woocommerce' ),
+						),
+						'color'  => array(
+							'type'        => ColorType::get(),
+							'description' => __( 'Filter widgets by color', 'woocommerce' ),
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Identifiable.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Identifiable.php
index 71bb3ba425b..a974f84529b 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Identifiable.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Identifiable.php
@@ -6,8 +6,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Interfaces;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\WidgetReview as WidgetReviewType;
-use Automattic\WooCommerce\Internal\Api\Schema\InterfaceType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InterfaceType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Identifiable {
 	private static ?InterfaceType $instance = null;
@@ -16,13 +16,13 @@ class Identifiable {
 		if ( null === self::$instance ) {
 			self::$instance = new InterfaceType(
 				array(
-					'name' => 'HasId',
+					'name'        => 'HasId',
 					'description' => __( 'An object with a numeric identifier', 'woocommerce' ),
-					'fields' => fn() => array(
+					'fields'      => fn() => array(
 						'id' => array(
-							'type' => Type::nonNull(Type::int()),
-								'description' => __( 'The unique numeric identifier', 'woocommerce' ),
-									),
+							'type'        => Type::nonNull( Type::int() ),
+							'description' => __( 'The unique numeric identifier', 'woocommerce' ),
+						),
 					),
 					'resolveType' => function ( $value ) {
 						$class = get_class( $value );
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Named.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Named.php
index 563b6b61295..6aa59d131e2 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Named.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Interfaces/Named.php
@@ -7,8 +7,8 @@ namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerat

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\Gadget as GadgetType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\Widget as WidgetType;
-use Automattic\WooCommerce\Internal\Api\Schema\InterfaceType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\InterfaceType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Named {
 	private static ?InterfaceType $instance = null;
@@ -17,17 +17,17 @@ class Named {
 		if ( null === self::$instance ) {
 			self::$instance = new InterfaceType(
 				array(
-					'name' => 'Named',
+					'name'        => 'Named',
 					'description' => __( 'An object with a human-readable label', 'woocommerce' ),
-					'fields' => fn() => array(
+					'fields'      => fn() => array(
 						'label' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'The display label for this object', 'woocommerce' ),
-									),
-						'id' => array(
-							'type' => Type::nonNull(Type::int()),
-								'description' => __( 'The unique numeric identifier', 'woocommerce' ),
-									),
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'The display label for this object', 'woocommerce' ),
+						),
+						'id'    => array(
+							'type'        => Type::nonNull( Type::int() ),
+							'description' => __( 'The unique numeric identifier', 'woocommerce' ),
+						),
 					),
 					'resolveType' => function ( $value ) {
 						$class = get_class( $value );
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Gadget.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Gadget.php
index 8a138f3fb80..0ae78148812 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Gadget.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Gadget.php
@@ -6,8 +6,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Interfaces\Named as NamedInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Gadget {
 	private static ?ObjectType $instance = null;
@@ -16,24 +16,24 @@ class Gadget {
 		if ( null === self::$instance ) {
 			self::$instance = new ObjectType(
 				array(
-					'name' => 'GadgetType',
+					'name'        => 'GadgetType',
 					'description' => __( 'A dummy gadget that uses a class-level #[Name] override', 'woocommerce' ),
-					'interfaces' => fn() => array(
-							NamedInterface::get(),
+					'interfaces'  => fn() => array(
+						NamedInterface::get(),
 					),
-					'fields' => fn() => array(
+					'fields'      => fn() => array(
 						'parts_count' => array(
-							'type' => Type::nonNull(Type::int()),
-								'description' => __( 'How many parts the gadget contains', 'woocommerce' ),
-										),
-						'label' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'The display label for this object', 'woocommerce' ),
-										),
-						'id' => array(
-							'type' => Type::nonNull(Type::int()),
-								'description' => __( 'The unique numeric identifier', 'woocommerce' ),
-										),
+							'type'        => Type::nonNull( Type::int() ),
+							'description' => __( 'How many parts the gadget contains', 'woocommerce' ),
+						),
+						'label'       => array(
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'The display label for this object', 'woocommerce' ),
+						),
+						'id'          => array(
+							'type'        => Type::nonNull( Type::int() ),
+							'description' => __( 'The unique numeric identifier', 'woocommerce' ),
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/OperationResult.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/OperationResult.php
index cb0e94353b3..0ab0cd9b501 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/OperationResult.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/OperationResult.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class OperationResult {
 	private static ?ObjectType $instance = null;
@@ -15,17 +15,17 @@ class OperationResult {
 		if ( null === self::$instance ) {
 			self::$instance = new ObjectType(
 				array(
-					'name' => 'OperationResult',
+					'name'        => 'OperationResult',
 					'description' => __( 'The result of a generic operation', 'woocommerce' ),
-					'fields' => fn() => array(
+					'fields'      => fn() => array(
 						'success' => array(
-							'type' => Type::nonNull(Type::boolean()),
-								'description' => __( 'Whether the operation succeeded', 'woocommerce' ),
-										),
+							'type'        => Type::nonNull( Type::boolean() ),
+							'description' => __( 'Whether the operation succeeded', 'woocommerce' ),
+						),
 						'message' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'A human-readable status message', 'woocommerce' ),
-										),
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'A human-readable status message', 'woocommerce' ),
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Widget.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Widget.php
index a58f4da92ae..8e9cd75b08c 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Widget.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/Widget.php
@@ -11,8 +11,8 @@ use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\Gra
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Pagination\WidgetReviewConnection as WidgetReviewConnectionType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Scalars\DummyDateTime as DummyDateTimeType;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Interfaces\Named as NamedInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class Widget {
 	private static ?ObjectType $instance = null;
@@ -21,68 +21,68 @@ class Widget {
 		if ( null === self::$instance ) {
 			self::$instance = new ObjectType(
 				array(
-					'name' => 'Widget',
+					'name'        => 'Widget',
 					'description' => __( 'A dummy widget that exercises every output-type attribute', 'woocommerce' ),
-					'interfaces' => fn() => array(
-							NamedInterface::get(),
+					'interfaces'  => fn() => array(
+						NamedInterface::get(),
 					),
-					'fields' => fn() => array(
-						'slug' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'A short slug', 'woocommerce' ),
-										),
-						'caption' => array(
-							'type' => Type::string(),
-								'description' => __( 'An optional caption', 'woocommerce' ),
-										),
-						'color' => array(
-							'type' => Type::nonNull(ColorType::get()),
-								'description' => __( 'The widget color', 'woocommerce' ),
-										),
-						'priority' => array(
-							'type' => Type::nonNull(PriorityType::get()),
-								'description' => __( 'Priority assigned to this widget', 'woocommerce' ),
-										),
-						'tag_ids' => array(
-							'type' => Type::nonNull(Type::listOf(Type::nonNull(Type::int()))),
-								'description' => __( 'Tag IDs assigned to this widget', 'woocommerce' ),
-										),
+					'fields'      => fn() => array(
+						'slug'             => array(
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'A short slug', 'woocommerce' ),
+						),
+						'caption'          => array(
+							'type'        => Type::string(),
+							'description' => __( 'An optional caption', 'woocommerce' ),
+						),
+						'color'            => array(
+							'type'        => Type::nonNull( ColorType::get() ),
+							'description' => __( 'The widget color', 'woocommerce' ),
+						),
+						'priority'         => array(
+							'type'        => Type::nonNull( PriorityType::get() ),
+							'description' => __( 'Priority assigned to this widget', 'woocommerce' ),
+						),
+						'tag_ids'          => array(
+							'type'        => Type::nonNull( Type::listOf( Type::nonNull( Type::int() ) ) ),
+							'description' => __( 'Tag IDs assigned to this widget', 'woocommerce' ),
+						),
 						'featured_reviews' => array(
-							'type' => Type::nonNull(Type::listOf(Type::nonNull(WidgetReview::get()))),
-								'description' => __( 'Notable comments left on this widget', 'woocommerce' ),
-										),
-						'reviews' => array(
-							'type' => Type::nonNull(WidgetReviewConnectionType::get()),
-								'description' => __( 'Reviews of the widget', 'woocommerce' ),
-										),
-						'date_created' => array(
-							'type' => DummyDateTimeType::get(),
-								'description' => __( 'When the widget was created', 'woocommerce' ),
-										),
-						'price' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'The widget price', 'woocommerce' ),
-									'args' => array(
-										'formatted' => array(
-									'type' => Type::boolean(),
-												'defaultValue' => false,
-												'description' => __( 'When true, prepend a $ sign', 'woocommerce' ),
-											),
-							),
+							'type'        => Type::nonNull( Type::listOf( Type::nonNull( WidgetReview::get() ) ) ),
+							'description' => __( 'Notable comments left on this widget', 'woocommerce' ),
+						),
+						'reviews'          => array(
+							'type'        => Type::nonNull( WidgetReviewConnectionType::get() ),
+							'description' => __( 'Reviews of the widget', 'woocommerce' ),
+						),
+						'date_created'     => array(
+							'type'        => DummyDateTimeType::get(),
+							'description' => __( 'When the widget was created', 'woocommerce' ),
+						),
+						'price'            => array(
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'The widget price', 'woocommerce' ),
+							'args'        => array(
+								'formatted' => array(
+									'type'         => Type::boolean(),
+									'defaultValue' => false,
+									'description'  => __( 'When true, prepend a $ sign', 'woocommerce' ),
 								),
-						'legacy_price' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'A field flagged for removal', 'woocommerce' ),
-										'deprecationReason' => 'Use price instead.',
 							),
-						'label' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'The display label for this object', 'woocommerce' ),
-										),
-						'id' => array(
-							'type' => Type::nonNull(Type::int()),
-								'description' => __( 'The unique numeric identifier', 'woocommerce' ),
-										),
+						),
+						'legacy_price'     => array(
+							'type'              => Type::nonNull( Type::string() ),
+							'description'       => __( 'A field flagged for removal', 'woocommerce' ),
+							'deprecationReason' => 'Use price instead.',
+						),
+						'label'            => array(
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'The display label for this object', 'woocommerce' ),
+						),
+						'id'               => array(
+							'type'        => Type::nonNull( Type::int() ),
+							'description' => __( 'The unique numeric identifier', 'woocommerce' ),
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/WidgetReview.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/WidgetReview.php
index 97b86a77992..bd5e6c71b0d 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/WidgetReview.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Output/WidgetReview.php
@@ -6,8 +6,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Interfaces\Identifiable as IdentifiableInterface;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class WidgetReview {
 	private static ?ObjectType $instance = null;
@@ -16,24 +16,24 @@ class WidgetReview {
 		if ( null === self::$instance ) {
 			self::$instance = new ObjectType(
 				array(
-					'name' => 'WidgetReview',
+					'name'        => 'WidgetReview',
 					'description' => __( 'A review left for a widget', 'woocommerce' ),
-					'interfaces' => fn() => array(
-							IdentifiableInterface::get(),
+					'interfaces'  => fn() => array(
+						IdentifiableInterface::get(),
 					),
-					'fields' => fn() => array(
-						'body' => array(
-							'type' => Type::nonNull(Type::string()),
-								'description' => __( 'The body of the review', 'woocommerce' ),
-										),
+					'fields'      => fn() => array(
+						'body'  => array(
+							'type'        => Type::nonNull( Type::string() ),
+							'description' => __( 'The body of the review', 'woocommerce' ),
+						),
 						'score' => array(
-							'type' => Type::nonNull(Type::int()),
-								'description' => __( 'A score between 0 and 5', 'woocommerce' ),
-										),
-						'id' => array(
-							'type' => Type::nonNull(Type::int()),
-								'description' => __( 'The unique numeric identifier', 'woocommerce' ),
-										),
+							'type'        => Type::nonNull( Type::int() ),
+							'description' => __( 'A score between 0 and 5', 'woocommerce' ),
+						),
+						'id'    => array(
+							'type'        => Type::nonNull( Type::int() ),
+							'description' => __( 'The unique numeric identifier', 'woocommerce' ),
+						),
 					),
 				)
 			);
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/PageInfo.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/PageInfo.php
index 3739cb27dee..3bfe0bb1ec5 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/PageInfo.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/PageInfo.php
@@ -5,8 +5,8 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Pagination;

-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class PageInfo {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetConnection.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetConnection.php
index c924fa5091a..22e9d82f9d0 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetConnection.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetConnection.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\Widget as WidgetType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class WidgetConnection {
 	private static ?ObjectType $instance = null;
@@ -21,14 +21,22 @@ class WidgetConnection {
 					'description' => __( 'A connection to a list of Widget items.', 'woocommerce' ),
 					'fields'      => fn() => array(
 						'edges'       => array(
-							'type' => Type::nonNull( Type::listOf( Type::nonNull(
-								WidgetEdge::get()
-							) ) ),
+							'type' => Type::nonNull(
+								Type::listOf(
+									Type::nonNull(
+										WidgetEdge::get()
+									)
+								)
+							),
 						),
 						'nodes'       => array(
-							'type' => Type::nonNull( Type::listOf( Type::nonNull(
-								WidgetType::get()
-							) ) ),
+							'type' => Type::nonNull(
+								Type::listOf(
+									Type::nonNull(
+										WidgetType::get()
+									)
+								)
+							),
 						),
 						'page_info'   => array(
 							'type' => Type::nonNull( PageInfo::get() ),
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetEdge.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetEdge.php
index a88fb098b33..2c70f8311ca 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetEdge.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetEdge.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\Widget as WidgetType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class WidgetEdge {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewConnection.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewConnection.php
index 573e158c704..324f62f6bd4 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewConnection.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewConnection.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\WidgetReview as WidgetReviewType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class WidgetReviewConnection {
 	private static ?ObjectType $instance = null;
@@ -21,14 +21,22 @@ class WidgetReviewConnection {
 					'description' => __( 'A connection to a list of WidgetReview items.', 'woocommerce' ),
 					'fields'      => fn() => array(
 						'edges'       => array(
-							'type' => Type::nonNull( Type::listOf( Type::nonNull(
-								WidgetReviewEdge::get()
-							) ) ),
+							'type' => Type::nonNull(
+								Type::listOf(
+									Type::nonNull(
+										WidgetReviewEdge::get()
+									)
+								)
+							),
 						),
 						'nodes'       => array(
-							'type' => Type::nonNull( Type::listOf( Type::nonNull(
-								WidgetReviewType::get()
-							) ) ),
+							'type' => Type::nonNull(
+								Type::listOf(
+									Type::nonNull(
+										WidgetReviewType::get()
+									)
+								)
+							),
 						),
 						'page_info'   => array(
 							'type' => Type::nonNull( PageInfo::get() ),
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewEdge.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewEdge.php
index adb2ae422cc..258fafb4fb0 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewEdge.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Pagination/WidgetReviewEdge.php
@@ -7,8 +7,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Pagination;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Output\WidgetReview as WidgetReviewType;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
-use Automattic\WooCommerce\Internal\Api\Schema\Type;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\Type;

 class WidgetReviewEdge {
 	private static ?ObjectType $instance = null;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Scalars/DummyDateTime.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Scalars/DummyDateTime.php
index 7b7409efee1..52fbb64b11e 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Scalars/DummyDateTime.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/GraphQLTypes/Scalars/DummyDateTime.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLTypes\Scalars;

 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Scalars\DummyDateTime as DummyDateTimeScalar;
-use Automattic\WooCommerce\Internal\Api\Schema\CustomScalarType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\CustomScalarType;

 class DummyDateTime {
 	private static ?CustomScalarType $instance = null;
@@ -22,18 +22,18 @@ class DummyDateTime {
 						try {
 							return DummyDateTimeScalar::parse( $value );
 						} catch ( \InvalidArgumentException $e ) {
-							throw new \Automattic\WooCommerce\Internal\Api\Schema\Error( $e->getMessage() );
+							throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error( $e->getMessage() );
 						}
 					},
 					'parseLiteral' => function ( $value_node, ?array $variables = null ) {
-						if ( $value_node instanceof \Automattic\WooCommerce\Internal\Api\Schema\AST\StringValueNode ) {
+						if ( $value_node instanceof \Automattic\WooCommerce\Api\Infrastructure\Schema\AST\StringValueNode ) {
 							try {
 								return DummyDateTimeScalar::parse( $value_node->value );
 							} catch ( \InvalidArgumentException $e ) {
-								throw new \Automattic\WooCommerce\Internal\Api\Schema\Error( $e->getMessage() );
+								throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error( $e->getMessage() );
 							}
 						}
-						throw new \Automattic\WooCommerce\Internal\Api\Schema\Error(
+						throw new \Automattic\WooCommerce\Api\Infrastructure\Schema\Error(
 							'DummyDateTime must be a string, got: ' . $value_node->kind
 						);
 					},
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootMutationType.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootMutationType.php
index 317c312f906..218c7615d56 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootMutationType.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootMutationType.php
@@ -8,7 +8,7 @@ namespace Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerat
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLMutations\Increment;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLMutations\CreateWidget;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLMutations\DeleteWidget;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;

 class RootMutationType {
 	private static ?ObjectType $instance = null;
@@ -19,7 +19,7 @@ class RootMutationType {
 				array(
 					'name'   => 'Mutation',
 					'fields' => fn() => array(
-						'increment' => Increment::get_field_definition(),
+						'increment'    => Increment::get_field_definition(),
 						'createWidget' => CreateWidget::get_field_definition(),
 						'deleteWidget' => DeleteWidget::get_field_definition(),
 					),
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootQueryType.php b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootQueryType.php
index 3d9ccc9cd2c..94c43ee40f8 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootQueryType.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/RootQueryType.php
@@ -21,8 +21,8 @@ use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\Gra
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries\FailingQuery;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries\ListWidgets;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\GraphQLQueries\GetGreeting;
-use Automattic\WooCommerce\Internal\Api\MetadataController;
-use Automattic\WooCommerce\Internal\Api\Schema\ObjectType;
+use Automattic\WooCommerce\Api\Infrastructure\MetadataController;
+use Automattic\WooCommerce\Api\Infrastructure\Schema\ObjectType;

 class RootQueryType {
 	private static ?ObjectType $instance = null;
@@ -33,22 +33,22 @@ class RootQueryType {
 				array(
 					'name'   => 'Query',
 					'fields' => fn() => array(
-						'namedThing' => GetIdentifiable::get_field_definition(),
-						'inheritedCap' => InheritedCapQuery::get_field_definition(),
-						'inheritedFromInterface' => InheritedFromInterfaceQuery::get_field_definition(),
-						'overriddenCap' => OverriddenCapQuery::get_field_definition(),
-						'mergedCaps' => MergedCapsQuery::get_field_definition(),
-						'inheritedPublic' => InheritedPublicQuery::get_field_definition(),
-						'widget' => GetWidget::get_field_definition(),
-						'authorizeThrows' => AuthorizeThrowsQuery::get_field_definition(),
-						'principalAware' => PrincipalAwareQuery::get_field_definition(),
-						'composedAuthorize' => ComposedAuthorizeQuery::get_field_definition(),
-						'ignoredAuthorize' => IgnoredAuthorizeQuery::get_field_definition(),
-						'overriddenAuthorize' => OverriddenAuthorizeQuery::get_field_definition(),
-						'authorizeOnly' => AuthorizeOnlyQuery::get_field_definition(),
-						'failing' => FailingQuery::get_field_definition(),
-						'widgets' => ListWidgets::get_field_definition(),
-						'greeting' => GetGreeting::get_field_definition(),
+						'namedThing'                   => GetIdentifiable::get_field_definition(),
+						'inheritedCap'                 => InheritedCapQuery::get_field_definition(),
+						'inheritedFromInterface'       => InheritedFromInterfaceQuery::get_field_definition(),
+						'overriddenCap'                => OverriddenCapQuery::get_field_definition(),
+						'mergedCaps'                   => MergedCapsQuery::get_field_definition(),
+						'inheritedPublic'              => InheritedPublicQuery::get_field_definition(),
+						'widget'                       => GetWidget::get_field_definition(),
+						'authorizeThrows'              => AuthorizeThrowsQuery::get_field_definition(),
+						'principalAware'               => PrincipalAwareQuery::get_field_definition(),
+						'composedAuthorize'            => ComposedAuthorizeQuery::get_field_definition(),
+						'ignoredAuthorize'             => IgnoredAuthorizeQuery::get_field_definition(),
+						'overriddenAuthorize'          => OverriddenAuthorizeQuery::get_field_definition(),
+						'authorizeOnly'                => AuthorizeOnlyQuery::get_field_definition(),
+						'failing'                      => FailingQuery::get_field_definition(),
+						'widgets'                      => ListWidgets::get_field_definition(),
+						'greeting'                     => GetGreeting::get_field_definition(),
 						MetadataController::FIELD_NAME => MetadataController::get_field_definition(),
 					),
 				)
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/api_generation_date.txt b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/api_generation_date.txt
index 17edde5142f..ce84cafa7c8 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/api_generation_date.txt
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/api_generation_date.txt
@@ -1 +1 @@
-2026-05-13T13:46:52+00:00
\ No newline at end of file
+2026-05-19T11:37:11+00:00
\ No newline at end of file
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/api_source_hash.txt b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/api_source_hash.txt
new file mode 100644
index 00000000000..80286b03311
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/Fixtures/DummyApiAutogenerated/api_source_hash.txt
@@ -0,0 +1 @@
+ec363c5fbb3e6b00910ae834390b114cba4d75123da6217f239a95618e5a270f
\ No newline at end of file
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerDebugModeTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerDebugModeTest.php
index 17ccb74c37d..5b41fed5d48 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerDebugModeTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerDebugModeTest.php
@@ -4,7 +4,7 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api;

-use Automattic\WooCommerce\Internal\Api\GraphQLController;
+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
 use Automattic\WooCommerce\Internal\Api\QueryCache;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver as DummyContainer;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Store as DummyStore;
@@ -12,7 +12,7 @@ use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\Gra
 use WC_REST_Unit_Test_Case;

 /**
- * Tests for {@see GraphQLController}'s debug-mode surface: the
+ * Tests for {@see GraphQLControllerBase}'s debug-mode surface: the
  * complexity / depth metrics surfaced under `extensions.debug`, the
  * previous-exception chain reporting, and the SerializationError →
  * BAD_USER_INPUT promotion path.
@@ -21,9 +21,9 @@ class GraphQLControllerDebugModeTest extends WC_REST_Unit_Test_Case {
 	/**
 	 * The system under test.
 	 *
-	 * @var GraphQLController
+	 * @var GraphQLControllerBase
 	 */
-	private GraphQLController $sut;
+	private GraphQLControllerBase $sut;

 	/**
 	 * Set up.
@@ -359,7 +359,7 @@ class GraphQLControllerDebugModeTest extends WC_REST_Unit_Test_Case {
 		add_filter( 'woocommerce_graphql_can_use_debug_mode', $filter );

 		try {
-			$reflection = new \ReflectionClass( GraphQLController::class );
+			$reflection = new \ReflectionClass( GraphQLControllerBase::class );
 			$method     = $reflection->getMethod( 'is_debug_mode' );
 			$method->setAccessible( true );

@@ -390,7 +390,7 @@ class GraphQLControllerDebugModeTest extends WC_REST_Unit_Test_Case {
 			}
 		};

-		$reflection = new \ReflectionClass( GraphQLController::class );
+		$reflection = new \ReflectionClass( GraphQLControllerBase::class );
 		$method     = $reflection->getMethod( 'is_debug_mode' );
 		$method->setAccessible( true );

diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerExecutionTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerExecutionTest.php
index 57a53e248d2..65a15c026d1 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerExecutionTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerExecutionTest.php
@@ -4,7 +4,7 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api;

-use Automattic\WooCommerce\Internal\Api\GraphQLController;
+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
 use Automattic\WooCommerce\Internal\Api\QueryCache;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver as DummyContainer;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Store as DummyStore;
@@ -12,7 +12,7 @@ use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\Gra
 use WC_REST_Unit_Test_Case;

 /**
- * End-to-end tests for {@see GraphQLController}, executing real requests
+ * End-to-end tests for {@see GraphQLControllerBase}, executing real requests
  * through a controller wired to the dummy fixture API.
  *
  * Covers the rules the controller enforces beyond what the schema itself
@@ -24,9 +24,9 @@ class GraphQLControllerExecutionTest extends WC_REST_Unit_Test_Case {
 	/**
 	 * The system under test.
 	 *
-	 * @var GraphQLController
+	 * @var GraphQLControllerBase
 	 */
-	private GraphQLController $sut;
+	private GraphQLControllerBase $sut;

 	/**
 	 * Set up.
@@ -595,7 +595,7 @@ class GraphQLControllerExecutionTest extends WC_REST_Unit_Test_Case {
 		add_filter( 'woocommerce_graphql_can_introspect', $filter );

 		try {
-			$reflection = new \ReflectionClass( GraphQLController::class );
+			$reflection = new \ReflectionClass( GraphQLControllerBase::class );
 			$method     = $reflection->getMethod( 'is_introspection_allowed' );
 			$method->setAccessible( true );

@@ -624,7 +624,7 @@ class GraphQLControllerExecutionTest extends WC_REST_Unit_Test_Case {
 			}
 		};

-		$reflection = new \ReflectionClass( GraphQLController::class );
+		$reflection = new \ReflectionClass( GraphQLControllerBase::class );
 		$method     = $reflection->getMethod( 'is_introspection_allowed' );
 		$method->setAccessible( true );

diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerStatusResolverTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerStatusResolverTest.php
index 421bbf9a372..e301fd22e1e 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerStatusResolverTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerStatusResolverTest.php
@@ -4,7 +4,7 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api;

-use Automattic\WooCommerce\Internal\Api\GraphQLController;
+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
 use Automattic\WooCommerce\Internal\Api\QueryCache;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver as DummyContainer;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Store as DummyStore;
@@ -24,7 +24,7 @@ use WC_REST_Unit_Test_Case;
  *
  * Test resolvers are wired into the controller via an anonymous subclass of
  * the dummy autogenerated controller that overrides
- * {@see GraphQLController::get_status_resolver()}. That mirrors the path
+ * {@see GraphQLControllerBase::get_status_resolver()}. That mirrors the path
  * ApiBuilder takes when emitting the autogenerated subclass for a plugin
  * that ships an `Infrastructure\HttpStatusResolver`.
  */
@@ -57,7 +57,7 @@ class GraphQLControllerStatusResolverTest extends WC_REST_Unit_Test_Case {
 	 *
 	 * @param ?object $resolver Status resolver to inject (or null for none).
 	 */
-	private function controller_with_resolver( ?object $resolver ): GraphQLController {
+	private function controller_with_resolver( ?object $resolver ): GraphQLControllerBase {
 		$controller = new class( $resolver ) extends DummyGraphQLController {
 			/**
 			 * The status resolver injected for this test, or null.
@@ -158,7 +158,7 @@ class GraphQLControllerStatusResolverTest extends WC_REST_Unit_Test_Case {
 		$this->assertSame( 405, $response->get_status() );

 		// Decision point #4 (final return): unhandled RuntimeException is
-		// caught inside Utils::translate_exceptions and surfaces as
+		// caught inside ResolverHelpers::translate_exceptions and surfaces as
 		// INTERNAL_ERROR → 500.
 		$response = $sut->handle_request(
 			$this->post_request( array( 'query' => '{ failing(kind: "runtime") { result } }' ) )
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerTest.php
index ccb4381703f..a898efe40d3 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLControllerTest.php
@@ -4,26 +4,26 @@ declare( strict_types = 1 );
 namespace Automattic\WooCommerce\Tests\Internal\Api;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLController as AutogeneratedGraphQLController;
-use Automattic\WooCommerce\Internal\Api\GraphQLController;
-use Automattic\WooCommerce\Internal\Api\Main;
+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
+use Automattic\WooCommerce\Api\Infrastructure\Main;
 use WC_REST_Unit_Test_Case;

 /**
- * Tests for the GraphQLController class — specifically the HTTP methods
+ * Tests for the GraphQLControllerBase class — specifically the HTTP methods
  * registered on the /wc/graphql route based on the GET endpoint option.
  */
 class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	/**
 	 * The System Under Test.
 	 *
-	 * @var GraphQLController
+	 * @var GraphQLControllerBase
 	 */
 	private $sut;

 	/**
 	 * Set up before each test.
 	 *
-	 * Skips on PHP < 8.1 because GraphQLController uses PHP 8.0+ syntax in its
+	 * Skips on PHP < 8.1 because GraphQLControllerBase uses PHP 8.0+ syntax in its
 	 * source file (named arguments). In production the class is only loaded
 	 * after {@see Main::is_enabled()} gates on PHP 8.1+; these tests bypass
 	 * that gate by hitting the DI container directly, so we replicate it here.
@@ -32,10 +32,10 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 		parent::setUp();

 		if ( PHP_VERSION_ID < 80100 ) {
-			$this->markTestSkipped( 'GraphQLController requires PHP 8.1+.' );
+			$this->markTestSkipped( 'GraphQLControllerBase requires PHP 8.1+.' );
 		}

-		// GraphQLController is abstract; instantiate the autogenerated subclass
+		// GraphQLControllerBase is abstract; instantiate the autogenerated subclass
 		// that wc_get_container() also uses via Main::handle_rest_api_init_for_core().
 		$this->sut = wc_get_container()->get( AutogeneratedGraphQLController::class );
 	}
@@ -86,7 +86,7 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	 */
 	public function test_get_endpoint_url_returns_default_when_option_unset(): void {
 		delete_option( Main::OPTION_ENDPOINT_URL );
-		$this->assertSame( GraphQLController::DEFAULT_ENDPOINT_URL, GraphQLController::get_endpoint_url() );
+		$this->assertSame( GraphQLControllerBase::DEFAULT_ENDPOINT_URL, GraphQLControllerBase::get_endpoint_url() );
 	}

 	/**
@@ -94,7 +94,7 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	 */
 	public function test_get_endpoint_url_returns_option_value_when_valid(): void {
 		update_option( Main::OPTION_ENDPOINT_URL, 'wc/v4/graphql' );
-		$this->assertSame( 'wc/v4/graphql', GraphQLController::get_endpoint_url() );
+		$this->assertSame( 'wc/v4/graphql', GraphQLControllerBase::get_endpoint_url() );
 	}

 	/**
@@ -102,7 +102,7 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	 */
 	public function test_get_endpoint_url_strips_surrounding_slashes(): void {
 		update_option( Main::OPTION_ENDPOINT_URL, '/wc/v4/graphql/' );
-		$this->assertSame( 'wc/v4/graphql', GraphQLController::get_endpoint_url() );
+		$this->assertSame( 'wc/v4/graphql', GraphQLControllerBase::get_endpoint_url() );
 	}

 	/**
@@ -113,7 +113,7 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	 */
 	public function test_get_endpoint_url_falls_back_on_invalid( string $value ): void {
 		update_option( Main::OPTION_ENDPOINT_URL, $value );
-		$this->assertSame( GraphQLController::DEFAULT_ENDPOINT_URL, GraphQLController::get_endpoint_url() );
+		$this->assertSame( GraphQLControllerBase::DEFAULT_ENDPOINT_URL, GraphQLControllerBase::get_endpoint_url() );
 	}

 	/**
@@ -151,8 +151,8 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	public function test_get_max_query_depth_returns_default_when_option_unset(): void {
 		delete_option( Main::OPTION_MAX_QUERY_DEPTH );
 		$this->assertSame(
-			GraphQLController::DEFAULT_MAX_QUERY_DEPTH,
-			GraphQLController::get_max_query_depth()
+			GraphQLControllerBase::DEFAULT_MAX_QUERY_DEPTH,
+			GraphQLControllerBase::get_max_query_depth()
 		);
 	}

@@ -161,7 +161,7 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	 */
 	public function test_get_max_query_depth_returns_option_value_when_positive(): void {
 		update_option( Main::OPTION_MAX_QUERY_DEPTH, '7' );
-		$this->assertSame( 7, GraphQLController::get_max_query_depth() );
+		$this->assertSame( 7, GraphQLControllerBase::get_max_query_depth() );
 	}

 	/**
@@ -173,8 +173,8 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	public function test_get_max_query_depth_falls_back_on_non_positive( string $value ): void {
 		update_option( Main::OPTION_MAX_QUERY_DEPTH, $value );
 		$this->assertSame(
-			GraphQLController::DEFAULT_MAX_QUERY_DEPTH,
-			GraphQLController::get_max_query_depth()
+			GraphQLControllerBase::DEFAULT_MAX_QUERY_DEPTH,
+			GraphQLControllerBase::get_max_query_depth()
 		);
 	}

@@ -184,8 +184,8 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	public function test_get_max_query_complexity_returns_default_when_option_unset(): void {
 		delete_option( Main::OPTION_MAX_QUERY_COMPLEXITY );
 		$this->assertSame(
-			GraphQLController::DEFAULT_MAX_QUERY_COMPLEXITY,
-			GraphQLController::get_max_query_complexity()
+			GraphQLControllerBase::DEFAULT_MAX_QUERY_COMPLEXITY,
+			GraphQLControllerBase::get_max_query_complexity()
 		);
 	}

@@ -194,7 +194,7 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	 */
 	public function test_get_max_query_complexity_returns_option_value_when_positive(): void {
 		update_option( Main::OPTION_MAX_QUERY_COMPLEXITY, '500' );
-		$this->assertSame( 500, GraphQLController::get_max_query_complexity() );
+		$this->assertSame( 500, GraphQLControllerBase::get_max_query_complexity() );
 	}

 	/**
@@ -206,8 +206,8 @@ class GraphQLControllerTest extends WC_REST_Unit_Test_Case {
 	public function test_get_max_query_complexity_falls_back_on_non_positive( string $value ): void {
 		update_option( Main::OPTION_MAX_QUERY_COMPLEXITY, $value );
 		$this->assertSame(
-			GraphQLController::DEFAULT_MAX_QUERY_COMPLEXITY,
-			GraphQLController::get_max_query_complexity()
+			GraphQLControllerBase::DEFAULT_MAX_QUERY_COMPLEXITY,
+			GraphQLControllerBase::get_max_query_complexity()
 		);
 	}

diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLEndpointRegistrarTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLEndpointRegistrarTest.php
index 276d5cd4a2a..35dcde85878 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLEndpointRegistrarTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/GraphQLEndpointRegistrarTest.php
@@ -6,7 +6,7 @@ namespace Automattic\WooCommerce\Tests\Internal\Api;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLController as AutogeneratedGraphQLController;
 use Automattic\WooCommerce\Internal\Api\GraphQLEndpointRegistrar;
-use Automattic\WooCommerce\Internal\Api\Main;
+use Automattic\WooCommerce\Api\Infrastructure\Main;
 use Automattic\WooCommerce\Internal\Features\FeaturesController;
 use WC_REST_Unit_Test_Case;

diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/HelperExceptionsTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/HelperExceptionsTest.php
index 4f4ed71f455..f97f2d691a1 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/HelperExceptionsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/HelperExceptionsTest.php
@@ -18,7 +18,7 @@ use WC_Unit_Test_Case;
  * the throw site.
  *
  * The actual code → status mapping that turns these into HTTP responses lives
- * in {@see \Automattic\WooCommerce\Internal\Api\GraphQLController} and is
+ * in {@see \Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase} and is
  * exercised end-to-end via {@see SecurityTest::test_invalid_token_error_code_maps_to_401()}
  * and similar; this file just verifies the exception classes themselves carry
  * the right metadata.
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/MainTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/MainTest.php
index 395fd7e50d5..2eeab68f1b8 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/MainTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/MainTest.php
@@ -5,8 +5,8 @@ declare(strict_types=1);
 namespace Automattic\WooCommerce\Tests\Internal\Api;

 use Automattic\WooCommerce\Internal\Api\Autogenerated\GraphQLController as AutogeneratedGraphQLController;
-use Automattic\WooCommerce\Internal\Api\GraphQLController;
-use Automattic\WooCommerce\Internal\Api\Main;
+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
+use Automattic\WooCommerce\Api\Infrastructure\Main;
 use Automattic\WooCommerce\Internal\Features\FeaturesController;
 use WC_Unit_Test_Case;

@@ -136,7 +136,7 @@ class MainTest extends WC_Unit_Test_Case {
 	public function test_instantiate_returns_controller_when_enabled(): void {
 		$controller = Main::instantiate_graphql_controller( AutogeneratedGraphQLController::class );

-		$this->assertInstanceOf( GraphQLController::class, $controller );
+		$this->assertInstanceOf( GraphQLControllerBase::class, $controller );
 	}

 	/**
@@ -154,7 +154,7 @@ class MainTest extends WC_Unit_Test_Case {
 	}

 	/**
-	 * @testdox register_graphql_endpoint rejects classes that are not GraphQLController subclasses.
+	 * @testdox register_graphql_endpoint rejects classes that are not GraphQLControllerBase subclasses.
 	 */
 	public function test_register_graphql_endpoint_rejects_unrelated_classes(): void {
 		$this->expectException( \InvalidArgumentException::class );
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/QueryCacheTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/QueryCacheTest.php
index 51fb1d8c681..7b3cbeb266a 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/QueryCacheTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/QueryCacheTest.php
@@ -3,7 +3,7 @@ declare( strict_types = 1 );

 namespace Automattic\WooCommerce\Tests\Internal\Api;

-use Automattic\WooCommerce\Internal\Api\Main;
+use Automattic\WooCommerce\Api\Infrastructure\Main;
 use Automattic\WooCommerce\Internal\Api\QueryCache;
 use Automattic\WooCommerce\Internal\Api\OpcacheFileExpiry;
 use Automattic\WooCommerce\Vendor\GraphQL\Language\AST\DocumentNode;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/SecurityTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/SecurityTest.php
index 3137eaf9394..621a6ea3fe1 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/SecurityTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/SecurityTest.php
@@ -4,7 +4,7 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\Api;

-use Automattic\WooCommerce\Internal\Api\GraphQLController;
+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
 use Automattic\WooCommerce\Internal\Api\QueryCache;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Infrastructure\ClassResolver as DummyContainer;
 use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApi\Store as DummyStore;
@@ -12,7 +12,7 @@ use Automattic\WooCommerce\Tests\Internal\Api\Fixtures\DummyApiAutogenerated\Gra
 use WC_REST_Unit_Test_Case;

 /**
- * Security-focused tests for {@see GraphQLController} and the resolvers it
+ * Security-focused tests for {@see GraphQLControllerBase} and the resolvers it
  * dispatches to.
  *
  * Anonymous and admin paths are covered elsewhere; this file pins down the
@@ -24,9 +24,9 @@ class SecurityTest extends WC_REST_Unit_Test_Case {
 	/**
 	 * The system under test.
 	 *
-	 * @var GraphQLController
+	 * @var GraphQLControllerBase
 	 */
-	private GraphQLController $sut;
+	private GraphQLControllerBase $sut;

 	/**
 	 * Set up.
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php
index de1d856a787..f8e6569a996 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php
@@ -3,8 +3,8 @@ declare( strict_types = 1 );

 namespace Automattic\WooCommerce\Tests\Internal\Api;

-use Automattic\WooCommerce\Internal\Api\GraphQLController;
-use Automattic\WooCommerce\Internal\Api\Main;
+use Automattic\WooCommerce\Api\Infrastructure\GraphQLControllerBase;
+use Automattic\WooCommerce\Api\Infrastructure\Main;
 use Automattic\WooCommerce\Internal\Api\QueryCache;
 use Automattic\WooCommerce\Internal\Api\Settings;
 use Automattic\WooCommerce\Internal\Features\FeaturesController;
@@ -121,7 +121,7 @@ class SettingsTest extends WC_Unit_Test_Case {

 		$this->assertArrayHasKey( Main::OPTION_ENDPOINT_URL, $by_id );
 		$this->assertSame( 'text', $by_id[ Main::OPTION_ENDPOINT_URL ]['type'] );
-		$this->assertSame( GraphQLController::DEFAULT_ENDPOINT_URL, $by_id[ Main::OPTION_ENDPOINT_URL ]['default'] );
+		$this->assertSame( GraphQLControllerBase::DEFAULT_ENDPOINT_URL, $by_id[ Main::OPTION_ENDPOINT_URL ]['default'] );
 	}

 	/**
@@ -243,7 +243,7 @@ class SettingsTest extends WC_Unit_Test_Case {
 		$this->assertArrayHasKey( Main::OPTION_MAX_QUERY_DEPTH, $by_id );
 		$this->assertSame( 'number', $by_id[ Main::OPTION_MAX_QUERY_DEPTH ]['type'] );
 		$this->assertSame(
-			(string) GraphQLController::DEFAULT_MAX_QUERY_DEPTH,
+			(string) GraphQLControllerBase::DEFAULT_MAX_QUERY_DEPTH,
 			$by_id[ Main::OPTION_MAX_QUERY_DEPTH ]['default']
 		);
 		$this->assertSame( '1', $by_id[ Main::OPTION_MAX_QUERY_DEPTH ]['custom_attributes']['min'] );
@@ -259,7 +259,7 @@ class SettingsTest extends WC_Unit_Test_Case {
 		$this->assertArrayHasKey( Main::OPTION_MAX_QUERY_COMPLEXITY, $by_id );
 		$this->assertSame( 'number', $by_id[ Main::OPTION_MAX_QUERY_COMPLEXITY ]['type'] );
 		$this->assertSame(
-			(string) GraphQLController::DEFAULT_MAX_QUERY_COMPLEXITY,
+			(string) GraphQLControllerBase::DEFAULT_MAX_QUERY_COMPLEXITY,
 			$by_id[ Main::OPTION_MAX_QUERY_COMPLEXITY ]['default']
 		);
 		$this->assertSame( '1', $by_id[ Main::OPTION_MAX_QUERY_COMPLEXITY ]['custom_attributes']['min'] );
diff --git a/plugins/woocommerce/tests/php/src/Internal/LegacyPhpApi/SettingsTest.php b/plugins/woocommerce/tests/php/src/Internal/LegacyPhpApi/SettingsTest.php
index fa801a8a234..8eda4bced40 100644
--- a/plugins/woocommerce/tests/php/src/Internal/LegacyPhpApi/SettingsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/LegacyPhpApi/SettingsTest.php
@@ -4,7 +4,7 @@ declare(strict_types=1);

 namespace Automattic\WooCommerce\Tests\Internal\LegacyPhpApi;

-use Automattic\WooCommerce\Internal\Api\Main;
+use Automattic\WooCommerce\Api\Infrastructure\Main;
 use Automattic\WooCommerce\Internal\Api\Settings;
 use Automattic\WooCommerce\Internal\Features\FeaturesController;
 use WC_Unit_Test_Case;