Repository: kubeflow/model-registry

Issue:
[MLMD Removal] Write DB migrations to recreate MLMD schemas and types using golang-migrate
### Description

The goal of this task is to implement database migration scripts using the golang-migrate tool in order to recreate the MLMD schemas and types directly within the Model Registry’s MySQL database. All necessary tables, indexes, constraints, and type mappings provided by MLMD should be replicated to ensure that the Model Registry API remains unchanged.

The migration scripts must support forward migrations to apply the new schema and rollback operations to revert if necessary. This ensures a safe transition process that maintains performance and data integrity throughout the deployment cycle.

### Acceptance Criteria

- Schema Accuracy

  - The migration scripts must accurately recreate all MLMD schemas including tables, columns, indexes, constraints, and custom types as currently exposed by MLMD.

- Tool Integration

  - Migrations must be written for and executed using the golang-migrate tool. They must successfully run on a fresh MySQL instance, as well as in integration testing environments.

- Rollback Capability

  - For every forward migration, a corresponding rollback (down migration) script must be provided to allow for a safe reversal without data loss or corruption.

- API and Performance Consistency

  - Integration tests must verify that the new internal metadata service interacting with the migrated database is fully compliant with the existing Model Registry API, and that performance does not degrade compared to the legacy MLMD-driven setup.

- Documentation and Testing

  - Complete documentation outlining the execution and rollback process for the migrations must be provided.
  - integration testing results should confirm that the recreated schema supports all required CRUD operations as expected.

Discussion:
@Al-Pragliola: closed by https://github.com/kubeflow/model-registry/pull/1107 and https://github.com/kubeflow/model-registry/pull/1148

Solution patch:
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 272be5e6..a54d1877 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -14,8 +14,8 @@
 - All the commits have been [_signed-off_](https://github.com/kubeflow/community/tree/master/dco-signoff-hook#signing-off-commits)  (To pass the `DCO` check)
 
 <!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
-- [ ] The commits have meaningful messages; the author will squash them after approval or in case of manual merges will ask to merge with squash.
-- [ ] Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
+- [ ] The commits have meaningful messages
+- [ ] Automated tests are provided as part of the PR for major new functionalities; testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
 - [ ] The developer has manually tested the changes and verified that the changes work.
 - [ ] Code changes follow the [kubeflow contribution guidelines](https://www.kubeflow.org/docs/about/contributing/).
 - [ ] **For first time contributors**: Please reach out to the [Reviewers](../OWNERS) to ensure all tests are being run, ensuring the label `ok-to-test` has been added to the PR.
diff --git a/.github/workflows/build-image-pr.yml b/.github/workflows/build-image-pr.yml
index 47ba7fc6..2e47f220 100644
--- a/.github/workflows/build-image-pr.yml
+++ b/.github/workflows/build-image-pr.yml
@@ -41,7 +41,6 @@ jobs:
       - name: Remove AppArmor profile for mysql in KinD on GHA # https://github.com/kubeflow/manifests/issues/2507
         run: |
           set -x
-          sudo apt-get install apparmor-profiles
           sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
       - name: Load Local Registry Test Image
         env:
diff --git a/.github/workflows/csi-test.yml b/.github/workflows/csi-test.yml
index 5f434ccd..6e097c0b 100644
--- a/.github/workflows/csi-test.yml
+++ b/.github/workflows/csi-test.yml
@@ -68,7 +68,6 @@ jobs:
       - name: Remove AppArmor profile for mysql in KinD on GHA # https://github.com/kubeflow/manifests/issues/2507
         run: |
           set -x
-          sudo apt-get install apparmor-profiles
           sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
 
       - name: Install kustomize
diff --git a/.github/workflows/first-time-contributor-pr.yml b/.github/workflows/first-time-contributor-pr.yml
index 2fbfa668..585be5cb 100644
--- a/.github/workflows/first-time-contributor-pr.yml
+++ b/.github/workflows/first-time-contributor-pr.yml
@@ -1,4 +1,4 @@
-name: Welcome first-time contributors
+name: Welcome first-time contributors (Beta)
 on:
   pull_request_target:
     types:
@@ -13,16 +13,38 @@ permissions:
 jobs:
   welcome:
     runs-on: ubuntu-latest
-    if: github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
     steps:
-      - name: Add a comment to the PR
+      - name: Check contributor status
+        id: check_1st_time_contrib
         uses: actions/github-script@v7
         with:
           script: |
-            github.rest.issues.createComment({
-              issue_number: context.issue.number,
+            const { data: pr } = await github.rest.pulls.get({
               owner: context.repo.owner,
               repo: context.repo.repo,
-              body: "Maintainers: let's ensure the label `ok-to-test` has been maintained and all the tests has been executed before merging.<br/><br/>Thank you for your first Pull Request!🎉🎉"
-            })
+              pull_number: context.issue.number
+            });
+            const isFirstTimeContributor = pr.user.contributions === 0;
+            console.log(`First-time contributor status: ${isFirstTimeContributor}`);
+            return { isFirstTimeContributor };
+
+      - name: Log contributor status (isFirstTimeContributor true)
+        if: steps.check_1st_time_contrib.outputs.isFirstTimeContributor == 'true'
+        run: echo "First-time contributor status is ${{ steps.check_1st_time_contrib.outputs.isFirstTimeContributor }}"
+    
+      - name: Log contributor status (isFirstTimeContributor false)
+        if: steps.check_1st_time_contrib.outputs.isFirstTimeContributor == 'false'
+        run: echo "First-time contributor status is ${{ steps.check_1st_time_contrib.outputs.isFirstTimeContributor }}"
+    
+      # - name: Add a comment to the PR if first time contributor
+      #   if: steps.check_1st_time_contrib.outputs.isFirstTimeContributor == 'true'
+      #   uses: actions/github-script@v7
+      #   with:
+      #     script: |
+      #       github.rest.issues.createComment({
+      #         issue_number: context.issue.number,
+      #         owner: context.repo.owner,
+      #         repo: context.repo.repo,
+      #         body: "Maintainers: let's ensure the label `ok-to-test` has been maintained and all the tests have been executed before merging.<br/><br/>Thank you for your first Pull Request! 🎉🎉"
+      #       })
 # do NOT: add actions/checkout to this flow, add-third party scripts, or auto-trigger CI jobs
diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml
index 12f4473a..25d437dc 100644
--- a/.github/workflows/python-tests.yml
+++ b/.github/workflows/python-tests.yml
@@ -197,7 +197,6 @@ jobs:
       - name: Remove AppArmor profile for mysql in KinD on GHA # https://github.com/kubeflow/manifests/issues/2507
         run: |
           set -x
-          sudo apt-get install apparmor-profiles
           sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
       - name: Load Local Registry Test Image
         env:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 137d02e8..d86b9959 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -14,11 +14,13 @@ The contributor's guide:
 * and [describes](https://www.kubeflow.org/docs/about/contributing/#owners-files-and-pr-workflow) the pull request and review workflow in detail, including the
   OWNERS files and automated workflow tool
 
+The [Kubeflow Community calendar](https://www.kubeflow.org/docs/about/community/#kubeflow-community-calendar) provides an overview of the community calls and specifically the bi-weekly Kubeflow Model Registry meeting.
+
 <hr/>
 
 The remainder of this document focuses on technical aspects while contributing to the Model Registry project specifically.
 
-Don't forget to reference the [Model Registry documentation](https://github.com/kubeflow/model-registry?tab=readme-ov-file#documentation-links) that details: what is a Model Registry, how to Install, logical model Concepts, how the MR python client works, Tutorials, FAQs and most importantly the [Technical References](https://github.com/kubeflow/model-registry?tab=readme-ov-file#documentation-links:~:text=FAQs-,Development,-introduction%20to%20local)!
+The [Model Registry documentation](https://github.com/kubeflow/model-registry?tab=readme-ov-file#documentation-links) provides details about: what is a Model Registry, how to Install, logical model Concepts, how the MR python client works, Tutorials, FAQs and most importantly the [Technical References](https://github.com/kubeflow/model-registry?tab=readme-ov-file#documentation-links:~:text=FAQs-,Development,-introduction%20to%20local)!
 
 # Contributing to Model Registry using Apple-silicon/ARM-based computers
 
diff --git a/Makefile b/Makefile
index a5e4019e..ff298dba 100644
--- a/Makefile
+++ b/Makefile
@@ -94,17 +94,14 @@ internal/converter/generated/converter.go: internal/converter/*.go
 .PHONY: gen/converter
 gen/converter: gen/grpc internal/converter/generated/converter.go
 
-YQ_EXPR := 'sort_keys(.components.schemas) | sort_keys(.paths) | sort_keys(.components.responses)'
-
-.PHONY: fmt/openapi
-fmt/openapi: api/openapi/model-registry.yaml bin/yq
-	@$(YQ) -i $(YQ_EXPR) $<
+api/openapi/model-registry.yaml: api/openapi/src/model-registry.yaml api/openapi/src/lib/*.yaml bin/yq
+	scripts/merge_openapi.sh model-registry.yaml
 
 # validate the openapi schema
 .PHONY: openapi/validate
-openapi/validate: api/openapi/model-registry.yaml bin/openapi-generator-cli bin/yq
-	@$(YQ) $(YQ_EXPR) $< | diff -u $< - || (echo "$< is incorrectly formatted. Run 'make fmt/openapi' to fix it."; exit 1)
-	$(OPENAPI_GENERATOR) validate -i $<
+openapi/validate: bin/openapi-generator-cli bin/yq
+	@scripts/merge_openapi.sh --check model-registry.yaml || (echo "api/openapi/model-registry.yaml is incorrectly formatted. Run 'make api/openapi/model-registry.yaml' to fix it."; exit 1)
+	$(OPENAPI_GENERATOR) validate -i api/openapi/model-registry.yaml
 
 # generate the openapi server implementation
 .PHONY: gen/openapi-server
@@ -115,7 +112,7 @@ internal/server/openapi/api_model_registry_service.go: bin/openapi-generator-cli
 
 # generate the openapi schema model and client
 .PHONY: gen/openapi
-gen/openapi: bin/openapi-generator-cli openapi/validate pkg/openapi/client.go
+gen/openapi: api/openapi/model-registry.yaml bin/openapi-generator-cli openapi/validate pkg/openapi/client.go
 
 pkg/openapi/client.go: bin/openapi-generator-cli api/openapi/model-registry.yaml clean-pkg-openapi
 	${OPENAPI_GENERATOR} generate \
diff --git a/ROADMAP.md b/ROADMAP.md
new file mode 100644
index 00000000..3ec3cb90
--- /dev/null
+++ b/ROADMAP.md
@@ -0,0 +1,23 @@
+# Kubeflow Model Registry Roadmap
+
+## Overview
+
+The Kubeflow Model Registry project roadmap is tracked using [GitHub Milestones](https://github.com/kubeflow/model-registry/milestones), following the Kubeflow Release Team's request: this approach has been recommended in order to maintain a detailed view of all the items intended for upcoming Kubeflow releases, organized by "themes". The roadmap is continuously updated as we make progress towards a Kubeflow Release.
+
+## Current Roadmap
+
+The current roadmap and upcoming features are tracked in our [GitHub Milestones](https://github.com/kubeflow/model-registry/milestones). Each milestone tracks specific or future Kubeflow release and contains the planned features, enhancements, and bug fixes. For each milestone, a GitHub Issue is typically attached serving as a Tracker record to provide additional details.
+
+## Past Roadmaps
+
+- Model Registry in Kubeflow 1.10
+    - [Milestone](https://github.com/kubeflow/model-registry/milestone/1)
+    - [Tracker for details](https://github.com/kubeflow/model-registry/issues/175)
+- Model Registry in Kubeflow 1.9
+    - [Tracker for details](https://github.com/kubeflow/model-registry/issues/3)
+
+## See also
+
+For more information about contributing to this project including the roadmap, refer to our [CONTRIBUTING.md](./CONTRIBUTING.md) file.
+
+For more information about the release process, refer to our [RELEASE.md](./RELEASE.md) file.
diff --git a/api/openapi/src/lib/common.yaml b/api/openapi/src/lib/common.yaml
new file mode 100644
index 00000000..c9e38dca
--- /dev/null
+++ b/api/openapi/src/lib/common.yaml
@@ -0,0 +1,362 @@
+components:
+  schemas:
+    BaseResource:
+      type: object
+      properties:
+        customProperties:
+          description: User provided custom properties which are not defined by its type.
+          type: object
+          additionalProperties:
+            $ref: "#/components/schemas/MetadataValue"
+        description:
+          description: |-
+            An optional description about the resource.
+          type: string
+        externalId:
+          description: |-
+            The external id that come from the clients’ system. This field is optional.
+            If set, it must be unique among all resources within a database instance.
+          type: string
+        name:
+          description: |-
+            The client provided name of the artifact. This field is optional. If set,
+            it must be unique among all the artifacts of the same artifact type within
+            a database instance and cannot be changed once set.
+          type: string
+        id:
+          format: int64
+          description: The unique server generated id of the resource.
+          type: string
+        createTimeSinceEpoch:
+          format: int64
+          description: Output only. Create time of the resource in millisecond since epoch.
+          type: string
+          readOnly: true
+        lastUpdateTimeSinceEpoch:
+          format: int64
+          description: |-
+            Output only. Last update time of the resource since epoch in millisecond
+            since epoch.
+          type: string
+          readOnly: true
+    BaseResourceCreate:
+      type: object
+      properties:
+        customProperties:
+          description: User provided custom properties which are not defined by its type.
+          type: object
+          additionalProperties:
+            $ref: "#/components/schemas/MetadataValue"
+        description:
+          description: |-
+            An optional description about the resource.
+          type: string
+        externalId:
+          description: |-
+            The external id that come from the clients’ system. This field is optional.
+            If set, it must be unique among all resources within a database instance.
+          type: string
+        name:
+          description: |-
+            The client provided name of the artifact. This field is optional. If set,
+            it must be unique among all the artifacts of the same artifact type within
+            a database instance and cannot be changed once set.
+          type: string
+    BaseResourceList:
+      required:
+        - nextPageToken
+        - pageSize
+        - size
+      type: object
+      properties:
+        nextPageToken:
+          description: Token to use to retrieve next page of results.
+          type: string
+        pageSize:
+          format: int32
+          description: Maximum number of resources to return in the result.
+          type: integer
+        size:
+          format: int32
+          description: Number of items in result list.
+          type: integer
+    BaseResourceUpdate:
+      type: object
+      properties:
+        customProperties:
+          description: User provided custom properties which are not defined by its type.
+          type: object
+          additionalProperties:
+            $ref: "#/components/schemas/MetadataValue"
+        description:
+          description: |-
+            An optional description about the resource.
+          type: string
+        externalId:
+          description: |-
+            The external id that come from the clients’ system. This field is optional.
+            If set, it must be unique among all resources within a database instance.
+          type: string
+    Error:
+      description: Error code and message.
+      required:
+        - code
+        - message
+      type: object
+      properties:
+        code:
+          description: Error code
+          type: string
+        message:
+          description: Error message
+          type: string
+    MetadataBoolValue:
+      description: A bool property value.
+      type: object
+      required:
+        - metadataType
+        - bool_value
+      properties:
+        bool_value:
+          type: boolean
+        metadataType:
+          type: string
+          example: MetadataBoolValue
+          default: MetadataBoolValue
+    MetadataDoubleValue:
+      description: A double property value.
+      type: object
+      required:
+        - metadataType
+        - double_value
+      properties:
+        double_value:
+          format: double
+          type: number
+        metadataType:
+          type: string
+          example: MetadataDoubleValue
+          default: MetadataDoubleValue
+    MetadataIntValue:
+      description: An integer (int64) property value.
+      type: object
+      required:
+        - metadataType
+        - int_value
+      properties:
+        int_value:
+          format: int64
+          type: string
+        metadataType:
+          type: string
+          example: MetadataIntValue
+          default: MetadataIntValue
+    MetadataProtoValue:
+      description: A proto property value.
+      type: object
+      required:
+        - metadataType
+        - type
+        - proto_value
+      properties:
+        type:
+          description: url describing proto value
+          type: string
+        proto_value:
+          description: Base64 encoded bytes for proto value
+          type: string
+        metadataType:
+          type: string
+          example: MetadataProtoValue
+          default: MetadataProtoValue
+    MetadataStringValue:
+      description: A string property value.
+      type: object
+      required:
+        - metadataType
+        - string_value
+      properties:
+        string_value:
+          type: string
+        metadataType:
+          type: string
+          example: MetadataStringValue
+          default: MetadataStringValue
+    MetadataStructValue:
+      description: A struct property value.
+      type: object
+      required:
+        - metadataType
+        - struct_value
+      properties:
+        struct_value:
+          description: Base64 encoded bytes for struct value
+          type: string
+        metadataType:
+          type: string
+          example: MetadataStructValue
+          default: MetadataStructValue
+    MetadataValue:
+      oneOf:
+        - $ref: "#/components/schemas/MetadataIntValue"
+        - $ref: "#/components/schemas/MetadataDoubleValue"
+        - $ref: "#/components/schemas/MetadataStringValue"
+        - $ref: "#/components/schemas/MetadataStructValue"
+        - $ref: "#/components/schemas/MetadataProtoValue"
+        - $ref: "#/components/schemas/MetadataBoolValue"
+      discriminator:
+        propertyName: metadataType
+        mapping:
+          MetadataBoolValue: "#/components/schemas/MetadataBoolValue"
+          MetadataDoubleValue: "#/components/schemas/MetadataDoubleValue"
+          MetadataIntValue: "#/components/schemas/MetadataIntValue"
+          MetadataProtoValue: "#/components/schemas/MetadataProtoValue"
+          MetadataStringValue: "#/components/schemas/MetadataStringValue"
+          MetadataStructValue: "#/components/schemas/MetadataStructValue"
+      description: A value in properties.
+      example:
+        string_value: my_value
+        metadataType: MetadataStringValue
+    OrderByField:
+      description: Supported fields for ordering result entities.
+      enum:
+        - CREATE_TIME
+        - LAST_UPDATE_TIME
+        - ID
+      type: string
+    SortOrder:
+      description: Supported sort direction for ordering result entities.
+      enum:
+        - ASC
+        - DESC
+      type: string
+  responses:
+    BadRequest:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Error"
+      description: Bad Request parameters
+    Conflict:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Error"
+      description: Conflict with current state of target resource
+    InternalServerError:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Error"
+      description: Unexpected internal server error
+    NotFound:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Error"
+      description: The specified resource was not found
+    ServiceUnavailable:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Error"
+      description: Service is unavailable
+    Unauthorized:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Error"
+      description: Unauthorized
+    UnprocessableEntity:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Error"
+      description: Unprocessable Entity error
+  parameters:
+    id:
+      name: id
+      description: The ID of resource.
+      schema:
+        type: string
+      in: path
+      required: true
+    name:
+      examples:
+        name:
+          value: entity-name
+      name: name
+      description: Name of entity to search.
+      schema:
+        type: string
+      in: query
+      required: false
+    externalId:
+      examples:
+        externalId:
+          value: "10"
+      name: externalId
+      description: External ID of entity to search.
+      schema:
+        type: string
+      in: query
+      required: false
+    parentResourceId:
+      examples:
+        parentResourceId:
+          value: "10"
+      name: parentResourceId
+      description: ID of the parent resource to use for search.
+      schema:
+        type: string
+      in: query
+      required: false
+    pageSize:
+      examples:
+        pageSize:
+          value: "100"
+      name: pageSize
+      description: Number of entities in each page.
+      schema:
+        type: string
+      in: query
+      required: false
+    nextPageToken:
+      name: nextPageToken
+      description: Token to use to retrieve next page of results.
+      schema:
+        type: string
+      in: query
+      required: false
+    orderBy:
+      style: form
+      explode: true
+      examples:
+        orderBy:
+          value: ID
+      name: orderBy
+      description: Specifies the order by criteria for listing entities.
+      schema:
+        $ref: "#/components/schemas/OrderByField"
+      in: query
+      required: false
+    sortOrder:
+      style: form
+      explode: true
+      examples:
+        sortOrder:
+          value: DESC
+      name: sortOrder
+      description: "Specifies the sort order for listing entities, defaults to ASC."
+      schema:
+        $ref: "#/components/schemas/SortOrder"
+      in: query
+      required: false
+  securitySchemes:
+    Bearer:
+      scheme: bearer
+      bearerFormat: JWT
+      type: http
+      description: Bearer JWT scheme
+security:
+  - Bearer: []
diff --git a/api/openapi/src/model-registry.yaml b/api/openapi/src/model-registry.yaml
new file mode 100644
index 00000000..7fdc2041
--- /dev/null
+++ b/api/openapi/src/model-registry.yaml
@@ -0,0 +1,1985 @@
+openapi: 3.0.3
+info:
+  title: Model Registry REST API
+  version: v1alpha3
+  description: REST API for Model Registry to create and manage ML model metadata
+  license:
+    name: Apache 2.0
+    url: "https://www.apache.org/licenses/LICENSE-2.0"
+servers:
+  - url: "https://localhost:8080"
+  - url: "http://localhost:8080"
+paths:
+  /api/model_registry/v1alpha3/artifact:
+    summary: Path used to search for an artifact.
+    description: >-
+      The REST endpoint/path used to search for an `Artifact` entity.  This path contains a `GET` operation to perform the find task.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: findArtifact
+      summary: Get an Artifact that matches search parameters.
+      description: Gets the details of a single instance of an `Artifact` that matches search parameters.
+    parameters:
+      - $ref: "#/components/parameters/name"
+      - $ref: "#/components/parameters/externalId"
+      - $ref: "#/components/parameters/parentResourceId"
+  /api/model_registry/v1alpha3/artifacts:
+    summary: Path used to manage the list of artifacts.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `Artifact` entities.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/ArtifactListResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getArtifacts
+      summary: List All Artifacts
+      description: Gets a list of all `Artifact` entities.
+    post:
+      requestBody:
+        description: A new `Artifact` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ArtifactCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/ArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createArtifact
+      summary: Create an Artifact
+      description: Creates a new instance of an `Artifact`.
+  /api/model_registry/v1alpha3/artifacts/{id}:
+    summary: Path used to manage a single Artifact.
+    description: >-
+      The REST endpoint/path used to get and update single instances of an `Artifact`. This path contains `GET` and `PATCH` operations used to perform the get and update tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getArtifact
+      summary: Get an Artifact
+      description: Gets the details of a single instance of an `Artifact`.
+    patch:
+      requestBody:
+        description: Updated `Artifact` information.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ArtifactUpdate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: updateArtifact
+      summary: Update an Artifact
+      description: Updates an existing `Artifact`.
+    parameters:
+      - name: id
+        description: A unique identifier for an `Artifact`.
+        schema:
+          type: string
+        in: path
+        required: true
+  /api/model_registry/v1alpha3/inference_service:
+    summary: Path used to manage an instance of inferenceservice.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `InferenceService` entities.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/InferenceServiceResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: findInferenceService
+      summary: Get an InferenceServices that matches search parameters.
+      description: Gets the details of a single instance of `InferenceService` that matches search parameters.
+    parameters:
+      - $ref: "#/components/parameters/name"
+      - $ref: "#/components/parameters/externalId"
+      - $ref: "#/components/parameters/parentResourceId"
+  /api/model_registry/v1alpha3/inference_services:
+    summary: Path used to manage the list of inferenceservices.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `InferenceService` entities.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/InferenceServiceListResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getInferenceServices
+      summary: List All InferenceServices
+      description: Gets a list of all `InferenceService` entities.
+    post:
+      requestBody:
+        description: A new `InferenceService` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/InferenceServiceCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/InferenceServiceResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createInferenceService
+      summary: Create a InferenceService
+      description: Creates a new instance of a `InferenceService`.
+  "/api/model_registry/v1alpha3/inference_services/{inferenceserviceId}":
+    summary: Path used to manage a single InferenceService.
+    description: >-
+      The REST endpoint/path used to get and update single instances of an `InferenceService`. This path contains `GET` and `PATCH` operations used to perform the get and update tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/InferenceServiceResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getInferenceService
+      summary: Get a InferenceService
+      description: Gets the details of a single instance of a `InferenceService`.
+    patch:
+      requestBody:
+        description: Updated `InferenceService` information.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/InferenceServiceUpdate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/InferenceServiceResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: updateInferenceService
+      summary: Update a InferenceService
+      description: Updates an existing `InferenceService`.
+    parameters:
+      - name: inferenceserviceId
+        description: A unique identifier for a `InferenceService`.
+        schema:
+          type: string
+        in: path
+        required: true
+  "/api/model_registry/v1alpha3/inference_services/{inferenceserviceId}/model":
+    summary: Path used to manage a `RegisteredModel` associated with an `InferenceService`.
+    description: >-
+      The REST endpoint/path used to list the `RegisteredModel` entity for an `InferenceService`.  This path contains a `GET` operation to perform the get task.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/RegisteredModelResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getInferenceServiceModel
+      summary: Get InferenceService's RegisteredModel
+      description: Gets the `RegisteredModel` entity for the `InferenceService`.
+    parameters:
+      - name: inferenceserviceId
+        description: A unique identifier for a `InferenceService`.
+        schema:
+          type: string
+        in: path
+        required: true
+  "/api/model_registry/v1alpha3/inference_services/{inferenceserviceId}/serves":
+    summary: Path used to manage the list of `ServeModels` for a `InferenceService`.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `ServeModel` entities for a `InferenceService`.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/name"
+        - $ref: "#/components/parameters/externalId"
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/ServeModelListResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getInferenceServiceServes
+      summary: List All InferenceService's ServeModel actions
+      description: Gets a list of all `ServeModel` entities for the `InferenceService`.
+    post:
+      requestBody:
+        description: A new `ServeModel` to be associated with the `InferenceService`.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ServeModelCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/ServeModelResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createInferenceServiceServe
+      summary: Create a ServeModel action in a InferenceService
+      description: Creates a new instance of a `ServeModel` associated with `InferenceService`.
+    parameters:
+      - name: inferenceserviceId
+        description: A unique identifier for a `InferenceService`.
+        schema:
+          type: string
+        in: path
+        required: true
+  "/api/model_registry/v1alpha3/inference_services/{inferenceserviceId}/version":
+    summary: Path used to get the current `ModelVersion` associated with an `InferenceService`.
+    description: >-
+      The REST endpoint/path used to get the current `ModelVersion` entity for a `InferenceService`. This path contains a `GET` operation to perform the get task.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelVersionResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getInferenceServiceVersion
+      summary: Get InferenceService's ModelVersion
+      description: Gets the `ModelVersion` entity for the `InferenceService`.
+    parameters:
+      - name: inferenceserviceId
+        description: A unique identifier for a `InferenceService`.
+        schema:
+          type: string
+        in: path
+        required: true
+  /api/model_registry/v1alpha3/model_artifact:
+    summary: Path used to search for a modelartifact.
+    description: >-
+      The REST endpoint/path used to search for a `ModelArtifact` entity.  This path contains a `GET` operation to perform the find task.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: findModelArtifact
+      summary: Get a ModelArtifact that matches search parameters.
+      description: Gets the details of a single instance of a `ModelArtifact` that matches search parameters.
+    parameters:
+      - $ref: "#/components/parameters/name"
+      - $ref: "#/components/parameters/externalId"
+      - $ref: "#/components/parameters/parentResourceId"
+  /api/model_registry/v1alpha3/model_artifacts:
+    summary: Path used to manage the list of modelartifacts.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `ModelArtifact` entities.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelArtifactListResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getModelArtifacts
+      summary: List All ModelArtifacts
+      description: Gets a list of all `ModelArtifact` entities.
+    post:
+      requestBody:
+        description: A new `ModelArtifact` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ModelArtifactCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/ModelArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createModelArtifact
+      summary: Create a ModelArtifact
+      description: Creates a new instance of a `ModelArtifact`.
+  "/api/model_registry/v1alpha3/model_artifacts/{modelartifactId}":
+    summary: Path used to manage a single ModelArtifact.
+    description: >-
+      The REST endpoint/path used to get and update single instances of an `ModelArtifact`. This path contains `GET` and `PATCH` operations used to perform the get and update tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelArtifactResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getModelArtifact
+      summary: Get a ModelArtifact
+      description: Gets the details of a single instance of a `ModelArtifact`.
+    patch:
+      requestBody:
+        description: Updated `ModelArtifact` information.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ModelArtifactUpdate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: updateModelArtifact
+      summary: Update a ModelArtifact
+      description: Updates an existing `ModelArtifact`.
+    parameters:
+      - name: modelartifactId
+        description: A unique identifier for a `ModelArtifact`.
+        schema:
+          type: string
+        in: path
+        required: true
+  /api/model_registry/v1alpha3/model_version:
+    summary: Path used to search for a modelversion.
+    description: >-
+      The REST endpoint/path used to search for a `ModelVersion` entity.  This path contains a `GET` operation to perform the find task.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelVersionResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: findModelVersion
+      summary: Get a ModelVersion that matches search parameters.
+      description: Gets the details of a single instance of a `ModelVersion` that matches search parameters.
+    parameters:
+      - $ref: "#/components/parameters/name"
+      - $ref: "#/components/parameters/externalId"
+      - $ref: "#/components/parameters/parentResourceId"
+  /api/model_registry/v1alpha3/model_versions:
+    summary: Path used to manage the list of modelversions.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `ModelVersion` entities.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelVersionListResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getModelVersions
+      summary: List All ModelVersions
+      description: Gets a list of all `ModelVersion` entities.
+    post:
+      requestBody:
+        description: A new `ModelVersion` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ModelVersionCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/ModelVersionResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "422":
+          $ref: "#/components/responses/UnprocessableEntity"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createModelVersion
+      summary: Create a ModelVersion
+      description: Creates a new instance of a `ModelVersion`.
+  "/api/model_registry/v1alpha3/model_versions/{modelversionId}":
+    summary: Path used to manage a single ModelVersion.
+    description: >-
+      The REST endpoint/path used to get and update single instances of an `ModelVersion`. This path contains `GET` and `PATCH` operations used to perform the get and update tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelVersionResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getModelVersion
+      summary: Get a ModelVersion
+      description: Gets the details of a single instance of a `ModelVersion`.
+    patch:
+      requestBody:
+        description: Updated `ModelVersion` information.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ModelVersionUpdate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelVersionResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: updateModelVersion
+      summary: Update a ModelVersion
+      description: Updates an existing `ModelVersion`.
+    parameters:
+      - name: modelversionId
+        description: A unique identifier for a `ModelVersion`.
+        schema:
+          type: string
+        in: path
+        required: true
+  "/api/model_registry/v1alpha3/model_versions/{modelversionId}/artifacts":
+    summary: Path used to manage the list of artifacts for a modelversion.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `Artifact` entities for a `ModelVersion`.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/name"
+        - $ref: "#/components/parameters/externalId"
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/ArtifactListResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getModelVersionArtifacts
+      summary: List all artifacts associated with the `ModelVersion`
+    post:
+      requestBody:
+        description: A new or existing `Artifact` to be associated with the `ModelVersion`.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/Artifact"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ArtifactResponse"
+        "201":
+          $ref: "#/components/responses/ArtifactResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: upsertModelVersionArtifact
+      summary: Upsert an Artifact in a ModelVersion
+      description: Creates a new instance of an Artifact if needed and associates it with `ModelVersion`.
+    parameters:
+      - name: modelversionId
+        description: A unique identifier for a `ModelVersion`.
+        schema:
+          type: string
+        in: path
+        required: true
+  /api/model_registry/v1alpha3/registered_model:
+    summary: Path used to search for a registeredmodel.
+    description: >-
+      The REST endpoint/path used to search for a `RegisteredModel` entity.  This path contains a `GET` operation to perform the find task.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/RegisteredModelResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: findRegisteredModel
+      summary: Get a RegisteredModel that matches search parameters.
+      description: Gets the details of a single instance of a `RegisteredModel` that matches search parameters.
+    parameters:
+      - $ref: "#/components/parameters/name"
+      - $ref: "#/components/parameters/externalId"
+  /api/model_registry/v1alpha3/registered_models:
+    summary: Path used to manage the list of registeredmodels.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `RegisteredModel` entities.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/RegisteredModelListResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getRegisteredModels
+      summary: List All RegisteredModels
+      description: Gets a list of all `RegisteredModel` entities.
+    post:
+      requestBody:
+        description: A new `RegisteredModel` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/RegisteredModelCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/RegisteredModelResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createRegisteredModel
+      summary: Create a RegisteredModel
+      description: Creates a new instance of a `RegisteredModel`.
+  "/api/model_registry/v1alpha3/registered_models/{registeredmodelId}":
+    summary: Path used to manage a single RegisteredModel.
+    description: >-
+      The REST endpoint/path used to get and update single instances of an `RegisteredModel`. This path contains `GET` and `PATCH` operations used to perform the get and update tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/RegisteredModelResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getRegisteredModel
+      summary: Get a RegisteredModel
+      description: Gets the details of a single instance of a `RegisteredModel`.
+    patch:
+      requestBody:
+        description: Updated `RegisteredModel` information.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/RegisteredModelUpdate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/RegisteredModelResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: updateRegisteredModel
+      summary: Update a RegisteredModel
+      description: Updates an existing `RegisteredModel`.
+    parameters:
+      - name: registeredmodelId
+        description: A unique identifier for a `RegisteredModel`.
+        schema:
+          type: string
+        in: path
+        required: true
+  "/api/model_registry/v1alpha3/registered_models/{registeredmodelId}/versions":
+    summary: Path used to manage the list of modelversions for a registeredmodel.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `ModelVersion` entities for a `RegisteredModel`.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/name"
+        - $ref: "#/components/parameters/externalId"
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/ModelVersionListResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getRegisteredModelVersions
+      summary: List All RegisteredModel's ModelVersions
+      description: Gets a list of all `ModelVersion` entities for the `RegisteredModel`.
+    post:
+      requestBody:
+        description: A new `ModelVersion` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ModelVersion"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/ModelVersionResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createRegisteredModelVersion
+      summary: Create a ModelVersion in RegisteredModel
+      description: Creates a new instance of a `ModelVersion`.
+    parameters:
+      - name: registeredmodelId
+        description: A unique identifier for a `RegisteredModel`.
+        schema:
+          type: string
+        in: path
+        required: true
+  /api/model_registry/v1alpha3/serving_environment:
+    summary: Path used to find a servingenvironment.
+    description: >-
+      The REST endpoint/path used to search for a `ServingEnvironment` entity.  This path contains a `GET` operation to perform the find task.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ServingEnvironmentResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: findServingEnvironment
+      summary: Find ServingEnvironment
+      description: Finds a `ServingEnvironment` entity that matches query parameters.
+    parameters:
+      - $ref: "#/components/parameters/name"
+      - $ref: "#/components/parameters/externalId"
+  /api/model_registry/v1alpha3/serving_environments:
+    summary: Path used to manage the list of servingenvironments.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `ServingEnvironment` entities.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/ServingEnvironmentListResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getServingEnvironments
+      summary: List All ServingEnvironments
+      description: Gets a list of all `ServingEnvironment` entities.
+    post:
+      requestBody:
+        description: A new `ServingEnvironment` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ServingEnvironmentCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/ServingEnvironmentResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createServingEnvironment
+      summary: Create a ServingEnvironment
+      description: Creates a new instance of a `ServingEnvironment`.
+  "/api/model_registry/v1alpha3/serving_environments/{servingenvironmentId}":
+    summary: Path used to manage a single ServingEnvironment.
+    description: >-
+      The REST endpoint/path used to get and update single instances of an `ServingEnvironment`. This path contains `GET` and `PATCH` operations used to perform the get and update tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ServingEnvironmentResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getServingEnvironment
+      summary: Get a ServingEnvironment
+      description: Gets the details of a single instance of a `ServingEnvironment`.
+    patch:
+      requestBody:
+        description: Updated `ServingEnvironment` information.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/ServingEnvironmentUpdate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "200":
+          $ref: "#/components/responses/ServingEnvironmentResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: updateServingEnvironment
+      summary: Update a ServingEnvironment
+      description: Updates an existing `ServingEnvironment`.
+    parameters:
+      - name: servingenvironmentId
+        description: A unique identifier for a `ServingEnvironment`.
+        schema:
+          type: string
+        in: path
+        required: true
+  "/api/model_registry/v1alpha3/serving_environments/{servingenvironmentId}/inference_services":
+    summary: Path used to manage the list of `InferenceServices` for a `ServingEnvironment`.
+    description: >-
+      The REST endpoint/path used to list and create zero or more `InferenceService` entities for a `ServingEnvironment`.  This path contains a `GET` and `POST` operation to perform the list and create tasks, respectively.
+    get:
+      tags:
+        - ModelRegistryService
+      parameters:
+        - $ref: "#/components/parameters/name"
+        - $ref: "#/components/parameters/externalId"
+        - $ref: "#/components/parameters/pageSize"
+        - $ref: "#/components/parameters/orderBy"
+        - $ref: "#/components/parameters/sortOrder"
+        - $ref: "#/components/parameters/nextPageToken"
+      responses:
+        "200":
+          $ref: "#/components/responses/InferenceServiceListResponse"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: getEnvironmentInferenceServices
+      summary: List All ServingEnvironment's InferenceServices
+      description: Gets a list of all `InferenceService` entities for the `ServingEnvironment`.
+    post:
+      requestBody:
+        description: A new `InferenceService` to be created.
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/InferenceServiceCreate"
+        required: true
+      tags:
+        - ModelRegistryService
+      responses:
+        "201":
+          $ref: "#/components/responses/InferenceServiceResponse"
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "409":
+          $ref: "#/components/responses/Conflict"
+        "500":
+          $ref: "#/components/responses/InternalServerError"
+        "503":
+          $ref: "#/components/responses/ServiceUnavailable"
+      operationId: createEnvironmentInferenceService
+      summary: Create a InferenceService in ServingEnvironment
+      description: Creates a new instance of a `InferenceService`.
+    parameters:
+      - name: servingenvironmentId
+        description: A unique identifier for a `ServingEnvironment`.
+        schema:
+          type: string
+        in: path
+        required: true
+components:
+  schemas:
+    Artifact:
+      oneOf:
+        - $ref: "#/components/schemas/ModelArtifact"
+        - $ref: "#/components/schemas/DocArtifact"
+      discriminator:
+        propertyName: artifactType
+        mapping:
+          model-artifact: "#/components/schemas/ModelArtifact"
+          doc-artifact: "#/components/schemas/DocArtifact"
+      description: A metadata Artifact Entity.
+    ArtifactCreate:
+      description: An Artifact to be created.
+      oneOf:
+        - $ref: "#/components/schemas/ModelArtifactCreate"
+        - $ref: "#/components/schemas/DocArtifactCreate"
+      discriminator:
+        propertyName: artifactType
+        mapping:
+          model-artifact: "#/components/schemas/ModelArtifactCreate"
+          doc-artifact: "#/components/schemas/DocArtifactCreate"
+    ArtifactList:
+      description: A list of Artifact entities.
+      allOf:
+        - type: object
+          properties:
+            items:
+              description: Array of `Artifact` entities.
+              type: array
+              items:
+                $ref: "#/components/schemas/Artifact"
+          required:
+            - items
+        - $ref: "#/components/schemas/BaseResourceList"
+    ArtifactState:
+      description: |2-
+         - PENDING: A state indicating that the artifact may exist.
+         - LIVE: A state indicating that the artifact should exist, unless something
+        external to the system deletes it.
+         - MARKED_FOR_DELETION: A state indicating that the artifact should be deleted.
+         - DELETED: A state indicating that the artifact has been deleted.
+         - ABANDONED: A state indicating that the artifact has been abandoned, which may be
+        due to a failed or cancelled execution.
+         - REFERENCE: A state indicating that the artifact is a reference artifact. At
+        execution start time, the orchestrator produces an output artifact for
+        each output key with state PENDING. However, for an intermediate
+        artifact, this first artifact's state will be REFERENCE. Intermediate
+        artifacts emitted during a component's execution will copy the REFERENCE
+        artifact's attributes. At the end of an execution, the artifact state
+        should remain REFERENCE instead of being changed to LIVE.
+
+        See also: ml-metadata Artifact.State
+      default: UNKNOWN
+      enum:
+        - UNKNOWN
+        - PENDING
+        - LIVE
+        - MARKED_FOR_DELETION
+        - DELETED
+        - ABANDONED
+        - REFERENCE
+      type: string
+    ArtifactUpdate:
+      description: An Artifact to be updated.
+      oneOf:
+        - $ref: "#/components/schemas/ModelArtifactUpdate"
+        - $ref: "#/components/schemas/DocArtifactUpdate"
+      discriminator:
+        propertyName: artifactType
+        mapping:
+          model-artifact: "#/components/schemas/ModelArtifactUpdate"
+          doc-artifact: "#/components/schemas/DocArtifactUpdate"
+    DocArtifact:
+      description: A document.
+      allOf:
+        - $ref: "#/components/schemas/BaseResource"
+        - $ref: "#/components/schemas/DocArtifactCreate"
+        - type: object
+          properties:
+            artifactType:
+              type: string
+              default: "doc-artifact"
+    DocArtifactCreate:
+      description: A document artifact to be created.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceCreate"
+        - $ref: "#/components/schemas/DocArtifactUpdate"
+        - type: object
+          properties:
+            artifactType:
+              type: string
+              default: "doc-artifact"
+    DocArtifactUpdate:
+      description: A document artifact to be updated.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceUpdate"
+        - type: object
+          properties:
+            artifactType:
+              type: string
+              default: "doc-artifact"
+            uri:
+              description: |-
+                The uniform resource identifier of the physical artifact.
+                May be empty if there is no physical artifact.
+              type: string
+            state:
+              $ref: "#/components/schemas/ArtifactState"
+    ExecutionState:
+      description: |-
+        The state of the Execution. The state transitions are
+          NEW -> RUNNING -> COMPLETE | CACHED | FAILED | CANCELED
+        CACHED means the execution is skipped due to cached results.
+        CANCELED means the execution is skipped due to precondition not met. It is
+        different from CACHED in that a CANCELED execution will not have any event
+        associated with it. It is different from FAILED in that there is no
+        unexpected error happened and it is regarded as a normal state.
+
+        See also: ml-metadata Execution.State
+      default: UNKNOWN
+      enum:
+        - UNKNOWN
+        - NEW
+        - RUNNING
+        - COMPLETE
+        - FAILED
+        - CACHED
+        - CANCELED
+      type: string
+    InferenceService:
+      description: >-
+        An `InferenceService` entity in a `ServingEnvironment` represents a deployed `ModelVersion` from a `RegisteredModel` created by Model Serving.
+      allOf:
+        - $ref: "#/components/schemas/BaseResource"
+        - $ref: "#/components/schemas/InferenceServiceCreate"
+    InferenceServiceCreate:
+      description: >-
+        An `InferenceService` entity in a `ServingEnvironment` represents a deployed `ModelVersion` from a `RegisteredModel` created by Model Serving.
+      required:
+        - registeredModelId
+        - servingEnvironmentId
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceCreate"
+        - $ref: "#/components/schemas/InferenceServiceUpdate"
+        - type: object
+          properties:
+            registeredModelId:
+              description: ID of the `RegisteredModel` to serve.
+              type: string
+            servingEnvironmentId:
+              description: ID of the parent `ServingEnvironment` for this `InferenceService` entity.
+              type: string
+    InferenceServiceList:
+      description: List of InferenceServices.
+      allOf:
+        - type: object
+          properties:
+            items:
+              description: ""
+              type: array
+              items:
+                $ref: "#/components/schemas/InferenceService"
+              readOnly: false
+          required:
+            - items
+        - $ref: "#/components/schemas/BaseResourceList"
+    InferenceServiceState:
+      description: |-
+        - DEPLOYED: A state indicating that the `InferenceService` should be deployed.
+        - UNDEPLOYED: A state indicating that the `InferenceService` should be un-deployed.
+        The state indicates the desired state of inference service.
+        See the associated `ServeModel` for the actual status of service deployment action.
+      default: DEPLOYED
+      enum:
+        - DEPLOYED
+        - UNDEPLOYED
+      type: string
+    InferenceServiceUpdate:
+      description: >-
+        An `InferenceService` entity in a `ServingEnvironment` represents a deployed `ModelVersion` from a `RegisteredModel` created by Model Serving.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceUpdate"
+        - type: object
+          properties:
+            modelVersionId:
+              description: >-
+                ID of the `ModelVersion` to serve. If it's unspecified, then the latest `ModelVersion` by creation order will be served.
+              type: string
+            runtime:
+              description: Model runtime.
+              type: string
+            desiredState:
+              $ref: "#/components/schemas/InferenceServiceState"
+    ModelArtifact:
+      description: An ML model artifact.
+      allOf:
+        - $ref: "#/components/schemas/BaseResource"
+        - $ref: "#/components/schemas/ModelArtifactCreate"
+        - type: object
+          properties:
+            artifactType:
+              type: string
+              default: "model-artifact"
+    ModelArtifactCreate:
+      description: An ML model artifact.
+      properties:
+        artifactType:
+          type: string
+          default: "model-artifact"
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceCreate"
+        - $ref: "#/components/schemas/ModelArtifactUpdate"
+    ModelArtifactList:
+      description: List of ModelArtifact entities.
+      allOf:
+        - type: object
+          properties:
+            items:
+              description: Array of `ModelArtifact` entities.
+              type: array
+              items:
+                $ref: "#/components/schemas/ModelArtifact"
+          required:
+            - items
+        - $ref: "#/components/schemas/BaseResourceList"
+    ModelArtifactUpdate:
+      description: An ML model artifact to be updated.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceUpdate"
+        - type: object
+          properties:
+            artifactType:
+              type: string
+              default: "model-artifact"
+            modelFormatName:
+              description: Name of the model format.
+              type: string
+            storageKey:
+              description: Storage secret name.
+              type: string
+            storagePath:
+              description: Path for model in storage provided by `storageKey`.
+              type: string
+            modelFormatVersion:
+              description: Version of the model format.
+              type: string
+            serviceAccountName:
+              description: Name of the service account with storage secret.
+              type: string
+            modelSourceKind:
+              type: string
+              description: "A string identifier describing the source kind. It differentiates various sources of model artifacts.\nThis identifier should be agreed upon by producers and consumers of source model metadata.\nIt is not an enumeration to keep the source of model metadata open ended. \nE.g. Kubeflow pipelines could use `pipelines` to identify models it produces."
+            modelSourceClass:
+              type: string
+              description: |-
+                A subgroup within the source kind. It is a specific sub-component or instance within the source kind.
+                E.g. `pipelinerun` for a Kubeflow pipeline run.
+            modelSourceGroup:
+              type: string
+              description: "Unique identifier for a source group for models from source class. \nIt maps to a physical group of source models. \nE.g. a Kubernetes namespace where the pipeline run was executed."
+            modelSourceId:
+              type: string
+              description: |-
+                A unique identifier for a source model within kind, class, and group.
+                It should be a url friendly string if source supports using URLs to locate source models.
+                E.g. a pipeline run ID.
+            modelSourceName:
+              type: string
+              description: "A human-readable name for the source model. \nE.g. `my-project/1`, `ibm-granite/granite-3.1-8b-base:2.1.2`."
+            uri:
+              description: |-
+                The uniform resource identifier of the physical artifact.
+                May be empty if there is no physical artifact.
+              type: string
+            state:
+              $ref: "#/components/schemas/ArtifactState"
+    ModelVersion:
+      description: Represents a ModelVersion belonging to a RegisteredModel.
+      allOf:
+        - $ref: "#/components/schemas/ModelVersionCreate"
+        - $ref: "#/components/schemas/BaseResource"
+    ModelVersionCreate:
+      description: Represents a ModelVersion belonging to a RegisteredModel.
+      required:
+        - name
+        - registeredModelId
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceCreate"
+        - $ref: "#/components/schemas/ModelVersionUpdate"
+        - type: object
+          properties:
+            registeredModelId:
+              description: ID of the `RegisteredModel` to which this version belongs.
+              type: string
+            name:
+              description: |-
+                The client provided name of the model's version. It must be unique among all the ModelVersions of the same
+                type within a Model Registry instance and cannot be changed once set.
+              type: string
+    ModelVersionList:
+      description: List of ModelVersion entities.
+      allOf:
+        - type: object
+          properties:
+            items:
+              description: Array of `ModelVersion` entities.
+              type: array
+              items:
+                $ref: "#/components/schemas/ModelVersion"
+          required:
+            - items
+        - $ref: "#/components/schemas/BaseResourceList"
+    ModelVersionState:
+      description: |-
+        - LIVE: A state indicating that the `ModelVersion` exists
+        - ARCHIVED: A state indicating that the `ModelVersion` has been archived.
+      default: LIVE
+      enum:
+        - LIVE
+        - ARCHIVED
+      type: string
+    ModelVersionUpdate:
+      description: Represents a ModelVersion belonging to a RegisteredModel.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceUpdate"
+        - type: object
+          properties:
+            state:
+              $ref: "#/components/schemas/ModelVersionState"
+            author:
+              description: Name of the author.
+              type: string
+    RegisteredModel:
+      description: A registered model in model registry. A registered model has ModelVersion children.
+      allOf:
+        - $ref: "#/components/schemas/BaseResource"
+        - $ref: "#/components/schemas/RegisteredModelCreate"
+    RegisteredModelCreate:
+      description: A registered model in model registry. A registered model has ModelVersion children.
+      required:
+        - name
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceCreate"
+        - $ref: "#/components/schemas/RegisteredModelUpdate"
+        - type: object
+          properties:
+            name:
+              description: |-
+                The client provided name of the model. It must be unique among all the RegisteredModels of the same
+                type within a Model Registry instance and cannot be changed once set.
+              type: string
+    RegisteredModelList:
+      description: List of RegisteredModels.
+      allOf:
+        - type: object
+          properties:
+            items:
+              description: ""
+              type: array
+              items:
+                $ref: "#/components/schemas/RegisteredModel"
+              readOnly: false
+          required:
+            - items
+        - $ref: "#/components/schemas/BaseResourceList"
+    RegisteredModelState:
+      description: |-
+        - LIVE: A state indicating that the `RegisteredModel` exists
+        - ARCHIVED: A state indicating that the `RegisteredModel` has been archived.
+      default: LIVE
+      enum:
+        - LIVE
+        - ARCHIVED
+      type: string
+    RegisteredModelUpdate:
+      description: A registered model in model registry. A registered model has ModelVersion children.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceUpdate"
+        - type: object
+          properties:
+            owner:
+              type: string
+            state:
+              $ref: "#/components/schemas/RegisteredModelState"
+    ServeModel:
+      description: An ML model serving action.
+      allOf:
+        - $ref: "#/components/schemas/BaseResource"
+        - $ref: "#/components/schemas/ServeModelCreate"
+    ServeModelCreate:
+      description: An ML model serving action.
+      required:
+        - modelVersionId
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceCreate"
+        - $ref: "#/components/schemas/ServeModelUpdate"
+        - type: object
+          properties:
+            modelVersionId:
+              description: ID of the `ModelVersion` that was served in `InferenceService`.
+              type: string
+    ServeModelList:
+      description: List of ServeModel entities.
+      allOf:
+        - type: object
+          properties:
+            items:
+              description: Array of `ModelArtifact` entities.
+              type: array
+              items:
+                $ref: "#/components/schemas/ServeModel"
+          required:
+            - items
+        - $ref: "#/components/schemas/BaseResourceList"
+    ServeModelUpdate:
+      description: An ML model serving action.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceUpdate"
+        - type: object
+          properties:
+            lastKnownState:
+              $ref: "#/components/schemas/ExecutionState"
+    ServingEnvironment:
+      description: A Model Serving environment for serving `RegisteredModels`.
+      allOf:
+        - $ref: "#/components/schemas/BaseResource"
+        - $ref: "#/components/schemas/ServingEnvironmentCreate"
+    ServingEnvironmentCreate:
+      description: A Model Serving environment for serving `RegisteredModels`.
+      required:
+        - name
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceCreate"
+        - $ref: "#/components/schemas/ServingEnvironmentUpdate"
+        - type: object
+          properties:
+            name:
+              description: The name of the ServingEnvironment.
+              type: string
+    ServingEnvironmentList:
+      description: List of ServingEnvironments.
+      allOf:
+        - type: object
+          properties:
+            items:
+              description: ""
+              type: array
+              items:
+                $ref: "#/components/schemas/ServingEnvironment"
+              readOnly: false
+          required:
+            - items
+        - $ref: "#/components/schemas/BaseResourceList"
+    ServingEnvironmentUpdate:
+      description: A Model Serving environment for serving `RegisteredModels`.
+      allOf:
+        - $ref: "#/components/schemas/BaseResourceUpdate"
+  responses:
+    ArtifactListResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ArtifactList"
+      description: A response containing a list of `Artifact` entities.
+      links:
+        GetArtifactById:
+          $ref: '#/components/links/GetArtifactById'
+        PatchArtifactById:
+          $ref: '#/components/links/PatchArtifactById'
+        SearchArtifactByExternalId:
+          $ref: '#/components/links/SearchArtifactByExternalId'
+        SearchArtifactByName:
+          $ref: '#/components/links/SearchArtifactByName'
+        SearchArtifactByParentResourceId:
+          $ref: '#/components/links/SearchArtifactByParentResourceId'
+    ArtifactResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/Artifact"
+      description: A response containing an `Artifact` entity.
+      links:
+        GetArtifactById:
+          $ref: '#/components/links/GetArtifactById'
+        PatchArtifactById:
+          $ref: '#/components/links/PatchArtifactById'
+        SearchArtifactByExternalId:
+          $ref: '#/components/links/SearchArtifactByExternalId'
+        SearchArtifactByName:
+          $ref: '#/components/links/SearchArtifactByName'
+        SearchArtifactByParentResourceId:
+          $ref: '#/components/links/SearchArtifactByParentResourceId'
+    InferenceServiceListResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/InferenceServiceList"
+      description: A response containing a list of `InferenceService` entities.
+      links:
+        GetISById:
+          $ref: '#/components/links/GetISById'
+        PatchISById:
+          $ref: '#/components/links/PatchISById'
+        SearchISByExternalId:
+          $ref: '#/components/links/SearchISByExternalId'
+        SearchISByName:
+          $ref: '#/components/links/SearchISByName'
+        SearchISByParentResourceId:
+          $ref: '#/components/links/SearchISByParentResourceId'
+    InferenceServiceResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/InferenceService"
+      description: A response containing a `InferenceService` entity.
+      links:
+        GetISById:
+          $ref: '#/components/links/GetISById'
+        PatchISById:
+          $ref: '#/components/links/PatchISById'
+        SearchISByExternalId:
+          $ref: '#/components/links/SearchISByExternalId'
+        SearchISByName:
+          $ref: '#/components/links/SearchISByName'
+        SearchISByParentResourceId:
+          $ref: '#/components/links/SearchISByParentResourceId'
+    ModelArtifactListResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ModelArtifactList"
+      description: A response containing a list of ModelArtifact entities.
+      links:
+        GetModelArtifactById:
+          $ref: '#/components/links/GetModelArtifactById'
+        PatchModelArtifactById:
+          $ref: '#/components/links/PatchModelArtifactById'
+        SearchModelArtifactByExternalId:
+          $ref: '#/components/links/SearchModelArtifactByExternalId'
+        SearchModelArtifactByName:
+          $ref: '#/components/links/SearchModelArtifactByName'
+        SearchModelArtifactByParentResourceId:
+          $ref: '#/components/links/SearchModelArtifactByParentResourceId'
+    ModelArtifactResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ModelArtifact"
+      description: A response containing a `ModelArtifact` entity.
+      links:
+        GetModelArtifactById:
+          $ref: '#/components/links/GetModelArtifactById'
+        PatchModelArtifactById:
+          $ref: '#/components/links/PatchModelArtifactById'
+        SearchModelArtifactByExternalId:
+          $ref: '#/components/links/SearchModelArtifactByExternalId'
+        SearchModelArtifactByName:
+          $ref: '#/components/links/SearchModelArtifactByName'
+        SearchModelArtifactByParentResourceId:
+          $ref: '#/components/links/SearchModelArtifactByParentResourceId'
+    ModelVersionListResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ModelVersionList"
+      description: A response containing a list of `ModelVersion` entities.
+      links:
+        GetModelVersionById:
+          $ref: '#/components/links/GetModelVersionById'
+        PatchModelVersionById:
+          $ref: '#/components/links/PatchModelVersionById'
+        SearchModelVersionByExternalId:
+          $ref: '#/components/links/SearchModelVersionByExternalId'
+        SearchModelVersionByName:
+          $ref: '#/components/links/SearchModelVersionByName'
+    ModelVersionResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ModelVersion"
+      description: A response containing a `ModelVersion` entity.
+      links:
+        GetModelVersionById:
+          $ref: '#/components/links/GetModelVersionById'
+        PatchModelVersionById:
+          $ref: '#/components/links/PatchModelVersionById'
+        SearchModelVersionByExternalId:
+          $ref: '#/components/links/SearchModelVersionByExternalId'
+        SearchModelVersionByName:
+          $ref: '#/components/links/SearchModelVersionByName'
+    RegisteredModelListResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/RegisteredModelList"
+      description: A response containing a list of `RegisteredModel` entities.
+      links:
+        GetRegisteredModelById:
+          $ref: '#/components/links/GetRegisteredModelById'
+        PatchRegisteredModelById:
+          $ref: '#/components/links/PatchRegisteredModelById'
+        SearchRegisteredModelByExternalId:
+          $ref: '#/components/links/SearchRegisteredModelByExternalId'
+        SearchRegisteredModelByName:
+          $ref: '#/components/links/SearchRegisteredModelByName'
+    RegisteredModelResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/RegisteredModel"
+      description: A response containing a `RegisteredModel` entity.
+      links:
+        GetRegisteredModelById:
+          $ref: '#/components/links/GetRegisteredModelById'
+        PatchRegisteredModelById:
+          $ref: '#/components/links/PatchRegisteredModelById'
+        SearchRegisteredModelByExternalId:
+          $ref: '#/components/links/SearchRegisteredModelByExternalId'
+        SearchRegisteredModelByName:
+          $ref: '#/components/links/SearchRegisteredModelByName'
+    ServeModelListResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ServeModelList"
+      description: A response containing a list of `ServeModel` entities.
+    ServeModelResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ServeModel"
+      description: A response containing a `ServeModel` entity.
+    ServingEnvironmentListResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ServingEnvironmentList"
+      description: A response containing a list of `ServingEnvironment` entities.
+      links:
+        GetServingEnvironmentById:
+          $ref: '#/components/links/GetServingEnvironmentById'
+        PatchServingEnvironmentById:
+          $ref: '#/components/links/PatchServingEnvironmentById'
+        SearchServingEnvironmentByExternalId:
+          $ref: '#/components/links/SearchServingEnvironmentByExternalId'
+        SearchServingEnvironmentByName:
+          $ref: '#/components/links/SearchServingEnvironmentByName'
+    ServingEnvironmentResponse:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ServingEnvironment"
+      description: A response containing a `ServingEnvironment` entity.
+      links:
+        GetServingEnvironmentById:
+          $ref: '#/components/links/GetServingEnvironmentById'
+        PatchServingEnvironmentById:
+          $ref: '#/components/links/PatchServingEnvironmentById'
+        SearchServingEnvironmentByExternalId:
+          $ref: '#/components/links/SearchServingEnvironmentByExternalId'
+        SearchServingEnvironmentByName:
+          $ref: '#/components/links/SearchServingEnvironmentByName'
+  parameters: {}
+  securitySchemes: {}
+  links:
+    # Artifact
+    GetArtifactById:
+      operationId: getArtifact
+      parameters:
+        id: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `id` parameter in `GET /api/model_registry/v1alpha3/artifacts/{id}`.
+
+    PatchArtifactById:
+      operationId: updateArtifact
+      parameters:
+        id: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `id` parameter in `PATCH /api/model_registry/v1alpha3/artifacts/{id}`.
+
+    SearchArtifactByExternalId:
+      operationId: findArtifact
+      parameters:
+        externalId: "$response.body#/externalId"
+      description: >
+        The `externalId` value returned in the response can be used as the `externalId` parameter in `GET /api/model_registry/v1alpha3/artifact`.
+
+    SearchArtifactByName:
+      operationId: findArtifact
+      parameters:
+        name: "$response.body#/name"
+      description: >
+        The `name` value returned in the response can be used as the `name` parameter in `GET /api/model_registry/v1alpha3/artifact`.
+
+    # Unsure about this one
+    SearchArtifactByParentResourceId:
+      operationId: findArtifact
+      parameters:
+        parentResourceId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `parentResourceId` parameter in `GET /api/model_registry/v1alpha3/artifact`, assuming that the 'Artifact' entity is a parent to another 'Artifact' entity.
+
+    # InferenceService
+    GetISById:
+      operationId: getInferenceService
+      parameters:
+        inferenceserviceId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `id` parameter in `GET /api/model_registry/v1alpha3/inference_services/{inferenceserviceId}`.
+
+    PatchISById:
+      operationId: updateInferenceService
+      parameters:
+        inferenceserviceId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `id` parameter in `PATCH /api/model_registry/v1alpha3/inference_services/{inferenceserviceId}`.
+
+    SearchISByExternalId:
+      operationId: findInferenceService
+      parameters:
+        externalId: "$response.body#/externalId"
+      description: >
+        The `externalId` value returned in the response can be used as the `externalId` parameter in `GET /api/model_registry/v1alpha3/inference_service`.
+
+    SearchISByName:
+      operationId: findInferenceService
+      parameters:
+        name: "$response.body#/name"
+      description: >
+        The `name` value returned in the response can be used as the `name` parameter in `GET /api/model_registry/v1alpha3/inference_service`.
+
+    # Unsure about this one
+    SearchISByParentResourceId:
+      operationId: findInferenceService
+      parameters:
+        parentResourceId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `parentResourceId` parameter in GET /api/model_registry/v1alpha3/inference_service`, assuming that the 'InferenceService' entity is a parent to another 'InferenceService' entity.
+
+    # ModelArtifact
+    GetModelArtifactById:
+      operationId: getModelArtifact
+      parameters:
+        modelartifactId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `id` parameter in `GET "/api/model_registry/v1alpha3/model_artifacts/{modelartifactId}`.
+
+    PatchModelArtifactById:
+      operationId: updateModelArtifact
+      parameters:
+        modelartifactId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `id` parameter in `PATCH "/api/model_registry/v1alpha3/model_artifacts/{modelartifactId}`.
+
+    SearchModelArtifactByExternalId:
+      operationId: findModelArtifact
+      parameters:
+        externalId: "$response.body#/externalId"
+      description: >
+        The `externalId` value returned in the response can be used as the `externalId` parameter in `GET /api/model_registry/v1alpha3/model_artifact`.
+
+    SearchModelArtifactByName:
+      operationId: findModelArtifact
+      parameters:
+        name: "$response.body#/name"
+      description: >
+        The `name` value returned in the response can be used as the `name` parameter in `GET /api/model_registry/v1alpha3/model_artifact`.
+
+    # Unsure about this one
+    SearchModelArtifactByParentResourceId:
+      operationId: findModelArtifact
+      parameters:
+        parentResourceId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `parentResourceId` parameter in `GET /api/model_registry/v1alpha3/model_artifact`, assuming that the 'ModelArtifact' entity is a parent to another 'ModelArtifact' entity.
+
+    # RegisteredModel
+    GetRegisteredModelById:
+      operationId: getRegisteredModel
+      parameters:
+        registeredmodelId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `registeredmodelId` parameter in `GET /api/model_registry/v1alpha3/registered_models/{registeredmodelId}`.
+
+    PatchRegisteredModelById:
+      operationId: updateRegisteredModel
+      parameters:
+        registeredmodelId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `registeredmodelId` parameter in `PATCH /api/model_registry/v1alpha3/registered_models/{registeredmodelId}`.
+
+    SearchRegisteredModelByExternalId:
+      operationId: findRegisteredModel
+      parameters:
+        externalId: "$response.body#/externalId"
+      description: >
+        The `externalId` value returned in the response can be used as the `externalId` parameter in `GET /api/model_registry/v1alpha3/registered_model`.
+
+    SearchRegisteredModelByName:
+      operationId: findRegisteredModel
+      parameters:
+        name: "$response.body#/name"
+      description: >
+        The `name` value returned in the response can be used as the `name` parameter in `GET /api/model_registry/v1alpha3/registered_model`.
+
+    # ModelVersion
+    GetModelVersionById:
+      operationId: getModelVersion
+      parameters:
+        modelversionId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `modelversionId` parameter in `GET /api/model_registry/v1alpha3/model_versions/{modelversionId}`.
+
+    PatchModelVersionById:
+      operationId: updateModelVersion
+      parameters:
+        modelversionId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `modelversionId` parameter in `PATCH /api/model_registry/v1alpha3/model_versions/{modelversionId}`.
+
+    SearchModelVersionByExternalId:
+      operationId: findModelVersion
+      parameters:
+        externalId: "$response.body#/externalId"
+      description: >
+        The `externalId` value returned in the response can be used as the `externalId` parameter in `GET /api/model_registry/v1alpha3/model_version`.
+
+    SearchModelVersionByName:
+      operationId: findModelVersion
+      parameters:
+        name: "$response.body#/name"
+      description: >
+        The `name` value returned in the response can be used as the `name` parameter in `GET /api/model_registry/v1alpha3/model_version`.
+
+    # ServingEnvironment
+    GetServingEnvironmentById:
+      operationId: getServingEnvironment
+      parameters:
+        servingenvironmentId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `servingenvironmentId` parameter in `GET /api/model_registry/v1alpha3/serving_environments/{servingenvironmentId}`.
+
+    PatchServingEnvironmentById:
+      operationId: updateServingEnvironment
+      parameters:
+        servingenvironmentId: "$response.body#/id"
+      description: >
+        The `id` value returned in the response can be used as the `servingenvironmentId` parameter in `PATCH /api/model_registry/v1alpha3/serving_environments/{servingenvironmentId}`.
+
+    SearchServingEnvironmentByExternalId:
+      operationId: findServingEnvironment
+      parameters:
+        externalId: "$response.body#/externalId"
+      description: >
+        The `externalId` value returned in the response can be used as the `externalId` parameter in `GET /api/model_registry/v1alpha3/serving_environment`.
+
+    SearchServingEnvironmentByName:
+      operationId: findServingEnvironment
+      parameters:
+        name: "$response.body#/name"
+      description: >
+        The `name` value returned in the response can be used as the `name` parameter in `GET /api/model_registry/v1alpha3/serving_environment`.
+
+      #What about ServeModel?
+tags:
+  - name: ModelRegistryService
+    description: Model Registry Service REST API
diff --git a/clients/python/poetry.lock b/clients/python/poetry.lock
index 4977e652..bf9dbd05 100644
--- a/clients/python/poetry.lock
+++ b/clients/python/poetry.lock
@@ -311,19 +311,19 @@ uvloop = ["uvloop (>=0.15.2)"]
 
 [[package]]
 name = "boto3"
-version = "1.38.13"
+version = "1.38.18"
 description = "The AWS SDK for Python"
 optional = true
 python-versions = ">=3.9"
 groups = ["main"]
 markers = "extra == \"boto3\""
 files = [
-    {file = "boto3-1.38.13-py3-none-any.whl", hash = "sha256:668400d13889d2d2fcd66ce785cc0b0fc040681f58a9c7f67daa9149a52b6c63"},
-    {file = "boto3-1.38.13.tar.gz", hash = "sha256:6633bce2b73284acce1453ca85834c7c5a59e0dbcce1170be461cc079bdcdfcf"},
+    {file = "boto3-1.38.18-py3-none-any.whl", hash = "sha256:38ecb477ba9fc4edcf97133bf1fe33261ebec6c58d59982abff3cea167624211"},
+    {file = "boto3-1.38.18.tar.gz", hash = "sha256:bd723bfbc109bdc63e017ead74dd22f2cf8a7515e24e730870b8a70af823e626"},
 ]
 
 [package.dependencies]
-botocore = ">=1.38.13,<1.39.0"
+botocore = ">=1.38.18,<1.39.0"
 jmespath = ">=0.7.1,<2.0.0"
 s3transfer = ">=0.12.0,<0.13.0"
 
@@ -332,15 +332,15 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
 
 [[package]]
 name = "botocore"
-version = "1.38.13"
+version = "1.38.18"
 description = "Low-level, data-driven core of boto 3."
 optional = true
 python-versions = ">=3.9"
 groups = ["main"]
 markers = "extra == \"boto3\""
 files = [
-    {file = "botocore-1.38.13-py3-none-any.whl", hash = "sha256:de29fee43a1f02787fb5b3756ec09917d5661ed95b2b2d64797ab04196f69e14"},
-    {file = "botocore-1.38.13.tar.gz", hash = "sha256:22feee15753cd3f9f7179d041604078a1024701497d27b22be7c6707e8d13ccb"},
+    {file = "botocore-1.38.18-py3-none-any.whl", hash = "sha256:0b5ddf195f15218f30ec63d8aba9e55cf60af2984c068276b9fd206059043310"},
+    {file = "botocore-1.38.18.tar.gz", hash = "sha256:ae4c97383e797e9648f8721bb0217fd9efd228e9fbc661d83dc0959be083ec5c"},
 ]
 
 [package.dependencies]
@@ -789,45 +789,22 @@ files = [
     {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"},
 ]
 
-[[package]]
-name = "hf-xet"
-version = "1.1.0"
-description = ""
-optional = true
-python-versions = ">=3.8"
-groups = ["main"]
-markers = "extra == \"hf\" and (platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\")"
-files = [
-    {file = "hf_xet-1.1.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0322c42551e275fcb7949c083a54a81b2898e50787c9aa74284fcb8d2c58c12c"},
-    {file = "hf_xet-1.1.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:667153a0304ac2debf2af95a8ff7687186f885b493f4cd16344869af270cd110"},
-    {file = "hf_xet-1.1.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:995eeffb119636ea617b96c7d7bf3c3f5ea8727fa57974574e25d700b8532d48"},
-    {file = "hf_xet-1.1.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3aee847da362393331f515c4010d0aaa1c2669acfcca1f4b28946d6949cc0086"},
-    {file = "hf_xet-1.1.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:68c5813a6074aa36e12ef5983230e3b03148cce61e0fcdd294096493795565b4"},
-    {file = "hf_xet-1.1.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4ee9222bf9274b1c198b88a929de0b5a49349c4962d89c5b3b2f0f7f47d9761c"},
-    {file = "hf_xet-1.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:73153eab9abf3d6973b21e94a67ccba5d595c3e12feb8c0bf50be02964e7f126"},
-    {file = "hf_xet-1.1.0.tar.gz", hash = "sha256:a7c2a4c2b6eee9ce0a1a367a82b60d95ba634420ef1c250addad7aa4af419cf4"},
-]
-
-[package.extras]
-tests = ["pytest"]
-
 [[package]]
 name = "huggingface-hub"
-version = "0.31.1"
+version = "0.31.4"
 description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
 optional = true
 python-versions = ">=3.8.0"
 groups = ["main"]
 markers = "extra == \"hf\""
 files = [
-    {file = "huggingface_hub-0.31.1-py3-none-any.whl", hash = "sha256:43f73124819b48b42d140cbc0d7a2e6bd15b2853b1b9d728d4d55ad1750cac5b"},
-    {file = "huggingface_hub-0.31.1.tar.gz", hash = "sha256:492bb5f545337aa9e2f59b75ef4c5f535a371e8958a6ce90af056387e67f1180"},
+    {file = "huggingface_hub-0.31.4-py3-none-any.whl", hash = "sha256:4f70704760296cc69b612916056e9845f5490a33782b924fc531767967acc15d"},
+    {file = "huggingface_hub-0.31.4.tar.gz", hash = "sha256:5a7bc710b9f9c028aee5b1476867b4ec5c1b92f043cb364d5fdc54354757e4ce"},
 ]
 
 [package.dependencies]
 filelock = "*"
 fsspec = ">=2023.5.0"
-hf-xet = {version = ">=1.1.0,<2.0.0", markers = "platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\""}
 packaging = ">=20.9"
 pyyaml = ">=5.1"
 requests = "*"
@@ -840,7 +817,7 @@ cli = ["InquirerPy (==0.3.4)"]
 dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
 fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
 hf-transfer = ["hf-transfer (>=0.1.4)"]
-hf-xet = ["hf-xet (>=1.1.0,<2.0.0)"]
+hf-xet = ["hf-xet (>=1.1.1,<2.0.0)"]
 inference = ["aiohttp"]
 quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.9.0)"]
 tensorflow = ["graphviz", "pydot", "tensorflow"]
@@ -2009,30 +1986,30 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
 
 [[package]]
 name = "ruff"
-version = "0.11.9"
+version = "0.11.10"
 description = "An extremely fast Python linter and code formatter, written in Rust."
 optional = false
 python-versions = ">=3.7"
 groups = ["dev"]
 files = [
-    {file = "ruff-0.11.9-py3-none-linux_armv6l.whl", hash = "sha256:a31a1d143a5e6f499d1fb480f8e1e780b4dfdd580f86e05e87b835d22c5c6f8c"},
-    {file = "ruff-0.11.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:66bc18ca783b97186a1f3100e91e492615767ae0a3be584e1266aa9051990722"},
-    {file = "ruff-0.11.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bd576cd06962825de8aece49f28707662ada6a1ff2db848d1348e12c580acbf1"},
-    {file = "ruff-0.11.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b1d18b4be8182cc6fddf859ce432cc9631556e9f371ada52f3eaefc10d878de"},
-    {file = "ruff-0.11.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0f3f46f759ac623e94824b1e5a687a0df5cd7f5b00718ff9c24f0a894a683be7"},
-    {file = "ruff-0.11.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f34847eea11932d97b521450cf3e1d17863cfa5a94f21a056b93fb86f3f3dba2"},
-    {file = "ruff-0.11.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f33b15e00435773df97cddcd263578aa83af996b913721d86f47f4e0ee0ff271"},
-    {file = "ruff-0.11.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b27613a683b086f2aca8996f63cb3dd7bc49e6eccf590563221f7b43ded3f65"},
-    {file = "ruff-0.11.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e0d88756e63e8302e630cee3ce2ffb77859797cc84a830a24473939e6da3ca6"},
-    {file = "ruff-0.11.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:537c82c9829d7811e3aa680205f94c81a2958a122ac391c0eb60336ace741a70"},
-    {file = "ruff-0.11.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:440ac6a7029f3dee7d46ab7de6f54b19e34c2b090bb4f2480d0a2d635228f381"},
-    {file = "ruff-0.11.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:71c539bac63d0788a30227ed4d43b81353c89437d355fdc52e0cda4ce5651787"},
-    {file = "ruff-0.11.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c67117bc82457e4501473c5f5217d49d9222a360794bfb63968e09e70f340abd"},
-    {file = "ruff-0.11.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e4b78454f97aa454586e8a5557facb40d683e74246c97372af3c2d76901d697b"},
-    {file = "ruff-0.11.9-py3-none-win32.whl", hash = "sha256:7fe1bc950e7d7b42caaee2a8a3bc27410547cc032c9558ee2e0f6d3b209e845a"},
-    {file = "ruff-0.11.9-py3-none-win_amd64.whl", hash = "sha256:52edaa4a6d70f8180343a5b7f030c7edd36ad180c9f4d224959c2d689962d964"},
-    {file = "ruff-0.11.9-py3-none-win_arm64.whl", hash = "sha256:bcf42689c22f2e240f496d0c183ef2c6f7b35e809f12c1db58f75d9aa8d630ca"},
-    {file = "ruff-0.11.9.tar.gz", hash = "sha256:ebd58d4f67a00afb3a30bf7d383e52d0e036e6195143c6db7019604a05335517"},
+    {file = "ruff-0.11.10-py3-none-linux_armv6l.whl", hash = "sha256:859a7bfa7bc8888abbea31ef8a2b411714e6a80f0d173c2a82f9041ed6b50f58"},
+    {file = "ruff-0.11.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:968220a57e09ea5e4fd48ed1c646419961a0570727c7e069842edd018ee8afed"},
+    {file = "ruff-0.11.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1067245bad978e7aa7b22f67113ecc6eb241dca0d9b696144256c3a879663bca"},
+    {file = "ruff-0.11.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4854fd09c7aed5b1590e996a81aeff0c9ff51378b084eb5a0b9cd9518e6cff2"},
+    {file = "ruff-0.11.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b4564e9f99168c0f9195a0fd5fa5928004b33b377137f978055e40008a082c5"},
+    {file = "ruff-0.11.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6a9cc5b62c03cc1fea0044ed8576379dbaf751d5503d718c973d5418483641"},
+    {file = "ruff-0.11.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:607ecbb6f03e44c9e0a93aedacb17b4eb4f3563d00e8b474298a201622677947"},
+    {file = "ruff-0.11.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3a522fa389402cd2137df9ddefe848f727250535c70dafa840badffb56b7a4"},
+    {file = "ruff-0.11.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f071b0deed7e9245d5820dac235cbdd4ef99d7b12ff04c330a241ad3534319f"},
+    {file = "ruff-0.11.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a60e3a0a617eafba1f2e4186d827759d65348fa53708ca547e384db28406a0b"},
+    {file = "ruff-0.11.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:da8ec977eaa4b7bf75470fb575bea2cb41a0e07c7ea9d5a0a97d13dbca697bf2"},
+    {file = "ruff-0.11.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ddf8967e08227d1bd95cc0851ef80d2ad9c7c0c5aab1eba31db49cf0a7b99523"},
+    {file = "ruff-0.11.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5a94acf798a82db188f6f36575d80609072b032105d114b0f98661e1679c9125"},
+    {file = "ruff-0.11.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3afead355f1d16d95630df28d4ba17fb2cb9c8dfac8d21ced14984121f639bad"},
+    {file = "ruff-0.11.10-py3-none-win32.whl", hash = "sha256:dc061a98d32a97211af7e7f3fa1d4ca2fcf919fb96c28f39551f35fc55bdbc19"},
+    {file = "ruff-0.11.10-py3-none-win_amd64.whl", hash = "sha256:5cc725fbb4d25b0f185cb42df07ab6b76c4489b4bfb740a175f3a59c70e8a224"},
+    {file = "ruff-0.11.10-py3-none-win_arm64.whl", hash = "sha256:ef69637b35fb8b210743926778d0e45e1bffa850a7c61e428c6b971549b5f5d1"},
+    {file = "ruff-0.11.10.tar.gz", hash = "sha256:d522fb204b4959909ecac47da02830daec102eeb100fb50ea9554818d47a5fa6"},
 ]
 
 [[package]]
@@ -2056,20 +2033,25 @@ crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
 
 [[package]]
 name = "setuptools"
-version = "70.2.0"
+version = "78.1.1"
 description = "Easily download, build, install, upgrade, and uninstall Python packages"
 optional = false
-python-versions = ">=3.8"
-groups = ["docs"]
-markers = "python_version >= \"3.12\""
+python-versions = ">=3.9"
+groups = ["dev", "docs"]
 files = [
-    {file = "setuptools-70.2.0-py3-none-any.whl", hash = "sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05"},
-    {file = "setuptools-70.2.0.tar.gz", hash = "sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1"},
+    {file = "setuptools-78.1.1-py3-none-any.whl", hash = "sha256:c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561"},
+    {file = "setuptools-78.1.1.tar.gz", hash = "sha256:fcc17fd9cd898242f6b4adfaca46137a9edef687f43e6f78469692a5e70d851d"},
 ]
+markers = {docs = "python_version >= \"3.10\""}
 
 [package.extras]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-ruff (>=0.3.2) ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""]
+core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"]
+cover = ["pytest-cov"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
+enabler = ["pytest-enabler (>=2.2)"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
+type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"]
 
 [[package]]
 name = "six"
@@ -2363,14 +2345,14 @@ telegram = ["requests"]
 
 [[package]]
 name = "types-python-dateutil"
-version = "2.9.0.20241206"
+version = "2.9.0.20250516"
 description = "Typing stubs for python-dateutil"
 optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
 groups = ["dev"]
 files = [
-    {file = "types_python_dateutil-2.9.0.20241206-py3-none-any.whl", hash = "sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53"},
-    {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"},
+    {file = "types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93"},
+    {file = "types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5"},
 ]
 
 [[package]]
diff --git a/clients/python/pyproject.toml b/clients/python/pyproject.toml
index c99fb768..5ad96c5c 100644
--- a/clients/python/pyproject.toml
+++ b/clients/python/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "model-registry"
-version = "0.2.18"
+version = "0.2.19"
 description = "Client for Kubeflow Model Registry"
 authors = ["Isabella Basso do Amaral <idoamara@redhat.com>"]
 license = "Apache-2.0"
diff --git a/clients/python/src/model_registry/__init__.py b/clients/python/src/model_registry/__init__.py
index 9b433370..abdc5fc3 100644
--- a/clients/python/src/model_registry/__init__.py
+++ b/clients/python/src/model_registry/__init__.py
@@ -1,6 +1,6 @@
 """Main package for the Kubeflow model registry."""
 
-__version__ = "0.2.18"
+__version__ = "0.2.19"
 
 from ._client import ModelRegistry
 
diff --git a/clients/python/src/model_registry/types/contexts.py b/clients/python/src/model_registry/types/contexts.py
index 2d50c423..cb6b69d1 100644
--- a/clients/python/src/model_registry/types/contexts.py
+++ b/clients/python/src/model_registry/types/contexts.py
@@ -82,6 +82,18 @@ class ModelVersion(BaseResourceModel):
             else None,
         )
 
+    def __repr_str__(self, join_str: str) -> str:
+        """Overrides pydantic Representation.__repr_str__ to bring name to the front."""
+        result = []
+        for a, v in self.__repr_args__():
+            if a is None:
+                result.append(repr(v))
+            elif a == "name":
+                result.insert(0, f"{a}={v!r}")
+            else:
+                result.append(f"{a}={v!r}")
+        return join_str.join(result)
+
 
 class RegisteredModel(BaseResourceModel):
     """Represents a registered model.
@@ -131,3 +143,15 @@ class RegisteredModel(BaseResourceModel):
             if source.custom_properties
             else None,
         )
+
+    def __repr_str__(self, join_str: str) -> str:
+        """Overrides pydantic Representation.__repr_str__ to bring name to the front."""
+        result = []
+        for a, v in self.__repr_args__():
+            if a is None:
+                result.append(repr(v))
+            elif a == "name":
+                result.insert(0, f"{a}={v!r}")
+            else:
+                result.append(f"{a}={v!r}")
+        return join_str.join(result)
diff --git a/clients/ui/bff/go.mod b/clients/ui/bff/go.mod
index 6637bb8a..9b046a56 100644
--- a/clients/ui/bff/go.mod
+++ b/clients/ui/bff/go.mod
@@ -6,27 +6,27 @@ require (
 	github.com/brianvoe/gofakeit/v7 v7.1.2
 	github.com/google/uuid v1.6.0
 	github.com/julienschmidt/httprouter v1.3.0
-	github.com/kubeflow/model-registry v0.2.14
+	github.com/kubeflow/model-registry v0.2.17
 	github.com/onsi/ginkgo/v2 v2.23.4
 	github.com/onsi/gomega v1.37.0
 	github.com/rs/cors v1.11.1
 	github.com/stretchr/testify v1.10.0
-	k8s.io/api v0.33.0
-	k8s.io/apimachinery v0.33.0
-	k8s.io/client-go v0.33.0
-	sigs.k8s.io/controller-runtime v0.19.1
+	k8s.io/api v0.33.1
+	k8s.io/apimachinery v0.33.1
+	k8s.io/client-go v0.33.1
+	sigs.k8s.io/controller-runtime v0.20.4
 )
 
 require (
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
-	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
-	github.com/evanphx/json-patch/v5 v5.9.0 // indirect
-	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
+	github.com/emicklei/go-restful/v3 v3.12.2 // indirect
+	github.com/evanphx/json-patch/v5 v5.9.11 // indirect
+	github.com/fxamacker/cbor/v2 v2.8.0 // indirect
 	github.com/go-logr/logr v1.4.2 // indirect
 	github.com/go-logr/zapr v1.3.0 // indirect
-	github.com/go-openapi/jsonpointer v0.21.0 // indirect
-	github.com/go-openapi/jsonreference v0.20.2 // indirect
-	github.com/go-openapi/swag v0.23.0 // indirect
+	github.com/go-openapi/jsonpointer v0.21.1 // indirect
+	github.com/go-openapi/jsonreference v0.21.0 // indirect
+	github.com/go-openapi/swag v0.23.1 // indirect
 	github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/google/gnostic-models v0.6.9 // indirect
@@ -34,35 +34,34 @@ require (
 	github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mailru/easyjson v0.9.0 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
-	github.com/spf13/pflag v1.0.5 // indirect
+	github.com/spf13/pflag v1.0.6 // indirect
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
 	go.uber.org/automaxprocs v1.6.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
-	go.uber.org/zap v1.26.0 // indirect
-	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
-	golang.org/x/net v0.38.0 // indirect
-	golang.org/x/oauth2 v0.27.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/net v0.39.0 // indirect
+	golang.org/x/oauth2 v0.29.0 // indirect
 	golang.org/x/sys v0.32.0 // indirect
-	golang.org/x/term v0.30.0 // indirect
-	golang.org/x/text v0.23.0 // indirect
-	golang.org/x/time v0.9.0 // indirect
+	golang.org/x/term v0.31.0 // indirect
+	golang.org/x/text v0.24.0 // indirect
+	golang.org/x/time v0.11.0 // indirect
 	golang.org/x/tools v0.31.0 // indirect
-	google.golang.org/protobuf v1.36.5 // indirect
+	google.golang.org/protobuf v1.36.6 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/apiextensions-apiserver v0.31.0 // indirect
+	k8s.io/apiextensions-apiserver v0.32.3 // indirect
 	k8s.io/klog/v2 v2.130.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
-	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
-	sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
+	k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
+	sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
 	sigs.k8s.io/randfill v1.0.0 // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
 	sigs.k8s.io/yaml v1.4.0 // indirect
diff --git a/clients/ui/bff/go.sum b/clients/ui/bff/go.sum
index 0810ae5b..846b2e7b 100644
--- a/clients/ui/bff/go.sum
+++ b/clients/ui/bff/go.sum
@@ -4,31 +4,28 @@ github.com/brianvoe/gofakeit/v7 v7.1.2 h1:vSKaVScNhWVpf1rlyEKSvO8zKZfuDtGqoIHT//
 github.com/brianvoe/gofakeit/v7 v7.1.2/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA=
 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
-github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
-github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
-github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
-github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
-github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
-github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
+github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
+github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
+github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
+github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
 github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
 github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
 github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
-github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
-github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
-github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
-github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
-github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
-github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
-github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
+github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
+github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
+github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
+github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
 github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -51,17 +48,14 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/kubeflow/model-registry v0.2.14 h1:ZJmsWEvyecSRw91Irr2oLgyzCJKVJ0s+16ycxpZaEP0=
-github.com/kubeflow/model-registry v0.2.14/go.mod h1:iUN9ariCxPzMlmR5dAzuk2N62SR0dmE534Vn3vdsmU8=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/kubeflow/model-registry v0.2.17 h1:5VSZ2g8Zu7nAbu6onuTlcdg3TjRadH73mkkYgkKpSEE=
+github.com/kubeflow/model-registry v0.2.17/go.mod h1:cG1/kRUXo06uTJWp78qylPtB6Pd932M07vhawAqedt8=
+github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
+github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -80,29 +74,24 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
 github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
-github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
-github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
-github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
-github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
-github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
-github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
-github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
-github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
+github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
+github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
+github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
+github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM=
+github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
 github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
 github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
 github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
 github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
 github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@@ -115,23 +104,21 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
-golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
-golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
-golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
-golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
+golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
+golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
+golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
+golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -140,14 +127,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
 golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
-golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
-golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
+golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
+golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
-golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
-golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
-golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
+golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
+golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
+golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -158,10 +145,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
-gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
-google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
-google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
+gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -169,27 +156,26 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP
 gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
-k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
-k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk=
-k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk=
-k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
-k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
-k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
-k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
+k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
+k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
+k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
+k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
+k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
+k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
+k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
 k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
 k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
-k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
-k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk=
-sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
-sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
-sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
+k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
+k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
+sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
+sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
+sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
 sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
 sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
 sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
diff --git a/clients/ui/frontend/package-lock.json b/clients/ui/frontend/package-lock.json
index 5762abef..5332c226 100644
--- a/clients/ui/frontend/package-lock.json
+++ b/clients/ui/frontend/package-lock.json
@@ -32,8 +32,8 @@
         "@babel/preset-env": "^7.26.9",
         "@babel/preset-react": "^7.18.6",
         "@babel/preset-typescript": "^7.21.5",
-        "@cypress/code-coverage": "^3.13.12",
-        "@module-federation/enhanced": "^0.11.1",
+        "@cypress/code-coverage": "^3.14.1",
+        "@module-federation/enhanced": "^0.13.1",
         "@mui/icons-material": "^6.4.8",
         "@mui/material": "^6.1.7",
         "@mui/types": "^7.2.20",
@@ -59,8 +59,8 @@
         "cypress-axe": "^1.5.0",
         "cypress-high-resolution": "^1.0.0",
         "cypress-mochawesome-reporter": "^3.8.2",
-        "cypress-multi-reporters": "^2.0.4",
-        "dotenv": "^16.4.7",
+        "cypress-multi-reporters": "^2.0.5",
+        "dotenv": "^16.5.0",
         "dotenv-expand": "^5.1.0",
         "dotenv-webpack": "^6.0.0",
         "expect": "^29.7.0",
@@ -70,7 +70,7 @@
         "imagemin": "^9.0.0",
         "jest": "^29.7.0",
         "jest-environment-jsdom": "^29.7.0",
-        "junit-report-merger": "^7.0.0",
+        "junit-report-merger": "^7.0.1",
         "mini-css-extract-plugin": "^2.9.0",
         "postcss": "^8.4.49",
         "prettier": "^3.3.3",
@@ -1998,9 +1998,9 @@
       }
     },
     "node_modules/@cypress/code-coverage": {
-      "version": "3.13.12",
-      "resolved": "https://registry.npmjs.org/@cypress/code-coverage/-/code-coverage-3.13.12.tgz",
-      "integrity": "sha512-JPNlzk9xgCXRIcFCGoSy0qx3FFcaJOGjGkRAPYewYWLukZbcFSjxfNuoK6IMkaJb+miWdzLV0tsAko9eQDNBiA==",
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/@cypress/code-coverage/-/code-coverage-3.14.1.tgz",
+      "integrity": "sha512-sob/cht1BxEXwr0XC5XZbHWoit0UJmk3se/otx305BmxN9Mc33lTD625O3PAfOBPxfS7LKTZLAtryG5dURL62Q==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2247,6 +2247,380 @@
       "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
       "license": "MIT"
     },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
+      "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
+      "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
+      "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
+      "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
+      "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
+      "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
+      "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
+      "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
+      "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
+      "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
+      "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
+      "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
+      "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
+      "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
+      "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
+      "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
+      "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
+      "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
+      "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
+      "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
+      "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
+      "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/@eslint-community/eslint-utils": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
@@ -3001,13 +3375,39 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@modern-js/node-bundle-require": {
+      "version": "2.65.1",
+      "resolved": "https://registry.npmjs.org/@modern-js/node-bundle-require/-/node-bundle-require-2.65.1.tgz",
+      "integrity": "sha512-XpEkciVEfDbkkLUI662ZFlI9tXsUQtLXk4NRJDBGosNnk9uL2XszmC8sKsdCSLK8AYuPW2w6MTVWuJsOR0EU8A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@modern-js/utils": "2.65.1",
+        "@swc/helpers": "0.5.13",
+        "esbuild": "0.17.19"
+      }
+    },
+    "node_modules/@modern-js/utils": {
+      "version": "2.65.1",
+      "resolved": "https://registry.npmjs.org/@modern-js/utils/-/utils-2.65.1.tgz",
+      "integrity": "sha512-HrChf19F+6nALo5XPra8ycjhXGQfGi23+S7Y2FLfTKe8vaNnky8duT/XvRWpbS4pp3SQj8ryO8m/qWSsJ1Rogw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@swc/helpers": "0.5.13",
+        "caniuse-lite": "^1.0.30001520",
+        "lodash": "^4.17.21",
+        "rslog": "^1.1.0"
+      }
+    },
     "node_modules/@module-federation/bridge-react-webpack-plugin": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.11.1.tgz",
-      "integrity": "sha512-SUoJE7dEQZVUwBGN+mcMxLyQcQT0RAOZfcjp6Jq3uS6dTtEmJiR4KKGAaNYBlaszBh/HxmiM1U+zE3G126O7tQ==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.13.1.tgz",
+      "integrity": "sha512-3RgGd8KcRw5vibnxWa1NUWwfb0tKwn8OvHeQ4GFKzMvDLm+QpCgQd9LeTEBP38wZgGXVtIJR3y5FPnufWswFKw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/sdk": "0.11.1",
+        "@module-federation/sdk": "0.13.1",
         "@types/semver": "7.5.8",
         "semver": "7.6.3"
       }
@@ -3017,6 +3417,7 @@
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
       "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
       "dev": true,
+      "license": "ISC",
       "bin": {
         "semver": "bin/semver.js"
       },
@@ -3024,14 +3425,59 @@
         "node": ">=10"
       }
     },
+    "node_modules/@module-federation/cli": {
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/cli/-/cli-0.13.1.tgz",
+      "integrity": "sha512-ej7eZTVUiRMor37pkl2y3hbXwcaNvPgbZJVO+hb2c7cKBjWto7AndgR5qcKpcXXXlhbGwtnI+VrgldruKC+AqQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@modern-js/node-bundle-require": "2.65.1",
+        "@module-federation/dts-plugin": "0.13.1",
+        "@module-federation/sdk": "0.13.1",
+        "chalk": "3.0.0",
+        "commander": "11.1.0"
+      },
+      "bin": {
+        "mf": "bin/mf.js"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      }
+    },
+    "node_modules/@module-federation/cli/node_modules/chalk": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@module-federation/cli/node_modules/commander": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+      "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=16"
+      }
+    },
     "node_modules/@module-federation/data-prefetch": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-0.11.1.tgz",
-      "integrity": "sha512-94CiNMHqFdaP93RzzEkMyAQcjXMdlSrsMd9R0htzW23keSnerWnmTcRfkvuzKSAR5cqYszGlrYH9CLyMl1T56A==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-0.13.1.tgz",
+      "integrity": "sha512-hj3R72rRyune4fb4V4OFmo1Rfa9T9u0so2Q4vt69frPc2NV2FPPJkIvHGs/geGTLOgt4nn7OH1/ukmR3wWvSuA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/runtime": "0.11.1",
-        "@module-federation/sdk": "0.11.1",
+        "@module-federation/runtime": "0.13.1",
+        "@module-federation/sdk": "0.13.1",
         "fs-extra": "9.1.0"
       },
       "peerDependencies": {
@@ -3040,22 +3486,23 @@
       }
     },
     "node_modules/@module-federation/dts-plugin": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.11.1.tgz",
-      "integrity": "sha512-1fsnNb1dIYFoZ9Gk0gVXb/7+YDm0yWSBsVQvGLBOxMSaf1aF12mVi7MF9+l/ax4BgtgFvqVwekKssAbOXrjsig==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.13.1.tgz",
+      "integrity": "sha512-PQMs57h9s5pCkLWZ0IyDGCcac4VZ+GgJE40pAWrOQ+/AgTC+WFyAT16M7PsRENS57Qed4wWQwgfOjS9zmfxKJA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/error-codes": "0.11.1",
-        "@module-federation/managers": "0.11.1",
-        "@module-federation/sdk": "0.11.1",
-        "@module-federation/third-party-dts-extractor": "0.11.1",
+        "@module-federation/error-codes": "0.13.1",
+        "@module-federation/managers": "0.13.1",
+        "@module-federation/sdk": "0.13.1",
+        "@module-federation/third-party-dts-extractor": "0.13.1",
         "adm-zip": "^0.5.10",
         "ansi-colors": "^4.1.3",
         "axios": "^1.8.2",
         "chalk": "3.0.0",
         "fs-extra": "9.1.0",
         "isomorphic-ws": "5.0.0",
-        "koa": "2.15.4",
+        "koa": "2.16.1",
         "lodash.clonedeepwith": "4.5.0",
         "log4js": "6.9.1",
         "node-schedule": "2.1.1",
@@ -3077,6 +3524,7 @@
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
       "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "ansi-styles": "^4.1.0",
         "supports-color": "^7.1.0"
@@ -3086,24 +3534,30 @@
       }
     },
     "node_modules/@module-federation/enhanced": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.11.1.tgz",
-      "integrity": "sha512-B+2kWuzkwEZvpLxwiah2gxHov9Xw2fmXZKvMqBwDSGCOobTtdipAjAeG0AXm7mdEO1Xw/SkZgEDLYQxW27exjA==",
-      "dev": true,
-      "dependencies": {
-        "@module-federation/bridge-react-webpack-plugin": "0.11.1",
-        "@module-federation/data-prefetch": "0.11.1",
-        "@module-federation/dts-plugin": "0.11.1",
-        "@module-federation/error-codes": "0.11.1",
-        "@module-federation/inject-external-runtime-core-plugin": "0.11.1",
-        "@module-federation/managers": "0.11.1",
-        "@module-federation/manifest": "0.11.1",
-        "@module-federation/rspack": "0.11.1",
-        "@module-federation/runtime-tools": "0.11.1",
-        "@module-federation/sdk": "0.11.1",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.13.1.tgz",
+      "integrity": "sha512-jbbk68RnvNmusGGcXNXVDJAzJOFB/hV+RVV2wWNWmBOVkDZPiWj7aFb0cJAwc9EYZbPel3QzRitZJ73+SaH1IA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@module-federation/bridge-react-webpack-plugin": "0.13.1",
+        "@module-federation/cli": "0.13.1",
+        "@module-federation/data-prefetch": "0.13.1",
+        "@module-federation/dts-plugin": "0.13.1",
+        "@module-federation/error-codes": "0.13.1",
+        "@module-federation/inject-external-runtime-core-plugin": "0.13.1",
+        "@module-federation/managers": "0.13.1",
+        "@module-federation/manifest": "0.13.1",
+        "@module-federation/rspack": "0.13.1",
+        "@module-federation/runtime-tools": "0.13.1",
+        "@module-federation/sdk": "0.13.1",
         "btoa": "^1.2.1",
+        "schema-utils": "^4.3.0",
         "upath": "2.0.1"
       },
+      "bin": {
+        "mf": "bin/mf.js"
+      },
       "peerDependencies": {
         "typescript": "^4.9.0 || ^5.0.0",
         "vue-tsc": ">=1.0.24",
@@ -3122,40 +3576,44 @@
       }
     },
     "node_modules/@module-federation/error-codes": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.11.1.tgz",
-      "integrity": "sha512-N1cs1qwrO8cU/OzfnBbr+3FaVbrJk6QEAsQ8H+YxGRrh/kHsR2BKpZCX79jTG27oDbz45FLjQ98YucMMXC24EA==",
-      "dev": true
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.13.1.tgz",
+      "integrity": "sha512-azgGDBnFRfqlivHOl96ZjlFUFlukESz2Rnnz/pINiSqoBBNjUE0fcAZP4X6jgrVITuEg90YkruZa7pW9I3m7Uw==",
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/@module-federation/inject-external-runtime-core-plugin": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/inject-external-runtime-core-plugin/-/inject-external-runtime-core-plugin-0.11.1.tgz",
-      "integrity": "sha512-giayNxsx7XK86aIzydjtnn8UD8qYyBcVwmsFEEXXA02Jod36CGRFcd0eQ6TzgVEF7kE3iZkpHEKJBGontl32Qg==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/inject-external-runtime-core-plugin/-/inject-external-runtime-core-plugin-0.13.1.tgz",
+      "integrity": "sha512-K+ltl2AqVqlsvEds1PffCMLDMlC5lvdkyMXOfcZO6u0O4dZlaTtZbT32NchY7kIEvEsj0wyYhX1i2DnsbHpUBw==",
       "dev": true,
+      "license": "MIT",
       "peerDependencies": {
-        "@module-federation/runtime-tools": "0.11.1"
+        "@module-federation/runtime-tools": "0.13.1"
       }
     },
     "node_modules/@module-federation/managers": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.11.1.tgz",
-      "integrity": "sha512-qEgJE4qFfIaPVpGncsCvn5eqC6VJ8wT2jwPF2+27cpU5IqZwvfIBZlIjUkGEDPjUtbS10JdGKBfLFrcI+p9i5A==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.13.1.tgz",
+      "integrity": "sha512-vQMrqSFQxjSuGgByC2wcY7zUTmVfhzCyDpnCCq0PtaozK8DcgwsEMzrAT3dbg8ifGUmse/xiRIbTmS5leKK+UQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/sdk": "0.11.1",
+        "@module-federation/sdk": "0.13.1",
         "find-pkg": "2.0.0",
         "fs-extra": "9.1.0"
       }
     },
     "node_modules/@module-federation/manifest": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.11.1.tgz",
-      "integrity": "sha512-y4zoS4QJMn6OVtY3Wkq3khtjVCU3J8Pnb1CbjM5xoJ7jy/qZhTnDJd194czoQgzx4MnP+BR5jshEQha9GCFPzg==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.13.1.tgz",
+      "integrity": "sha512-XcuFtLycoR0jQj8op+w20V5n459blNBvGXe//AwkEppQERk8SM5kQgIPvOVbZ8zGx7tl/F2HGTDVZlhDiKzIew==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/dts-plugin": "0.11.1",
-        "@module-federation/managers": "0.11.1",
-        "@module-federation/sdk": "0.11.1",
+        "@module-federation/dts-plugin": "0.13.1",
+        "@module-federation/managers": "0.13.1",
+        "@module-federation/sdk": "0.13.1",
         "chalk": "3.0.0",
         "find-pkg": "2.0.0"
       }
@@ -3165,6 +3623,7 @@
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
       "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "ansi-styles": "^4.1.0",
         "supports-color": "^7.1.0"
@@ -3174,18 +3633,19 @@
       }
     },
     "node_modules/@module-federation/rspack": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.11.1.tgz",
-      "integrity": "sha512-hhikMBb7qSWCKtoCPO1QLoJwu4BsZPAKs9nychLXakMPQEGByrnh/upVb1C2wep2C4Ax9sjuFT7zD/3CdHOmGg==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.13.1.tgz",
+      "integrity": "sha512-+qz8sW99SYDULajjjn4rSNaI4rogEPVOZsBvT6y0PdfpMD/wZxvh5HlV0u7+5DgWEjgrdm0cJHBHChlIbV/CMQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/bridge-react-webpack-plugin": "0.11.1",
-        "@module-federation/dts-plugin": "0.11.1",
-        "@module-federation/inject-external-runtime-core-plugin": "0.11.1",
-        "@module-federation/managers": "0.11.1",
-        "@module-federation/manifest": "0.11.1",
-        "@module-federation/runtime-tools": "0.11.1",
-        "@module-federation/sdk": "0.11.1",
+        "@module-federation/bridge-react-webpack-plugin": "0.13.1",
+        "@module-federation/dts-plugin": "0.13.1",
+        "@module-federation/inject-external-runtime-core-plugin": "0.13.1",
+        "@module-federation/managers": "0.13.1",
+        "@module-federation/manifest": "0.13.1",
+        "@module-federation/runtime-tools": "0.13.1",
+        "@module-federation/sdk": "0.13.1",
         "btoa": "1.2.1"
       },
       "peerDependencies": {
@@ -3203,47 +3663,52 @@
       }
     },
     "node_modules/@module-federation/runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.11.1.tgz",
-      "integrity": "sha512-yxxa/TRXaNggb34N+oL82J7r9+GZ3gYTCDyGibYqtsC5j7+9oB4tmc0UyhjrGMhg+fF8TAWFZjNKo7ZnyN9LcQ==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.13.1.tgz",
+      "integrity": "sha512-ZHnYvBquDm49LiHfv6fgagMo/cVJneijNJzfPh6S0CJrPS2Tay1bnTXzy8VA5sdIrESagYPaskKMGIj7YfnPug==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/error-codes": "0.11.1",
-        "@module-federation/runtime-core": "0.11.1",
-        "@module-federation/sdk": "0.11.1"
+        "@module-federation/error-codes": "0.13.1",
+        "@module-federation/runtime-core": "0.13.1",
+        "@module-federation/sdk": "0.13.1"
       }
     },
     "node_modules/@module-federation/runtime-core": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.11.1.tgz",
-      "integrity": "sha512-6KxLfkCl05Ey69Xg/dsjf7fPit9qGXZ0lpwaG2agiCqC3JCDxYjT7tgGvnWhTXCcztb/ThpT+bHrRD4Kw8SMhA==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.13.1.tgz",
+      "integrity": "sha512-TfyKfkSAentKeuvSsAItk8s5tqQSMfIRTPN2e1aoaq/kFhE+7blps719csyWSX5Lg5Es7WXKMsXHy40UgtBtuw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/error-codes": "0.11.1",
-        "@module-federation/sdk": "0.11.1"
+        "@module-federation/error-codes": "0.13.1",
+        "@module-federation/sdk": "0.13.1"
       }
     },
     "node_modules/@module-federation/runtime-tools": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.11.1.tgz",
-      "integrity": "sha512-8UqMbHJSdkEvKlnlXpR/OjMA77bUbhtmv0I4UO+PA1zBga4y3/St6NOjD66NTINKeWEgsCt1aepXHspduXp33w==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.13.1.tgz",
+      "integrity": "sha512-GEF1pxqLc80osIMZmE8j9UKZSaTm2hX2lql8tgIH/O9yK4wnF06k6LL5Ah+wJt+oJv6Dj55ri/MoxMP4SXoPNA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/runtime": "0.11.1",
-        "@module-federation/webpack-bundler-runtime": "0.11.1"
+        "@module-federation/runtime": "0.13.1",
+        "@module-federation/webpack-bundler-runtime": "0.13.1"
       }
     },
     "node_modules/@module-federation/sdk": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.11.1.tgz",
-      "integrity": "sha512-QS6zevdQYLCGF6NFf0LysMGARh+dZxMeoRKKDUW5PYi3XOk+tjJ7QsDKybfcBZBNgBJfIuwxh4Oei6WOFJEfRg==",
-      "dev": true
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.13.1.tgz",
+      "integrity": "sha512-bmf2FGQ0ymZuxYnw9bIUfhV3y6zDhaqgydEjbl4msObKMLGXZqhse2pTIIxBFpIxR1oONKX/y2FAolDCTlWKiw==",
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/@module-federation/third-party-dts-extractor": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.11.1.tgz",
-      "integrity": "sha512-oyyelSLGFObM699p192Cuk/LxEDdzSOywDUXrzPa/qSKNFii5WartjQRc4QPMLnsQaGD7fQVTTiBkvVBcWUdyQ==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.13.1.tgz",
+      "integrity": "sha512-0kWSupoC0aTxFjJZE5TVPNsoZ9kBsZhkvRxFnUW2vDYLgtvgs2dIrDlNlIXYiS/MaQCNHGyvdNepbchKQiwFaw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "find-pkg": "2.0.0",
         "fs-extra": "9.1.0",
@@ -3251,13 +3716,14 @@
       }
     },
     "node_modules/@module-federation/webpack-bundler-runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.11.1.tgz",
-      "integrity": "sha512-XlVegGyCBBLId8Jr6USjPOFYViQ0CCtoYjHpC8y1FOGtuXLGrvnEdFcl4XHlFlp3MY3Rxhr8QigrdZhYe5bRWg==",
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.13.1.tgz",
+      "integrity": "sha512-QSuSIGa09S8mthbB1L6xERqrz+AzPlHR6D7RwAzssAc+IHf40U6NiTLPzUqp9mmKDhC5Tm0EISU0ZHNeJpnpBQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@module-federation/runtime": "0.11.1",
-        "@module-federation/sdk": "0.11.1"
+        "@module-federation/runtime": "0.13.1",
+        "@module-federation/sdk": "0.13.1"
       }
     },
     "node_modules/@mui/core-downloads-tracker": {
@@ -4611,6 +5077,16 @@
       "dev": true,
       "license": "Apache-2.0"
     },
+    "node_modules/@swc/helpers": {
+      "version": "0.5.13",
+      "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz",
+      "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "^2.4.0"
+      }
+    },
     "node_modules/@swc/types": {
       "version": "0.1.17",
       "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz",
@@ -5192,7 +5668,8 @@
       "version": "7.5.8",
       "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
       "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/@types/send": {
       "version": "0.17.4",
@@ -5815,6 +6292,7 @@
       "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
       "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=12.0"
       }
@@ -6375,10 +6853,11 @@
       }
     },
     "node_modules/axios": {
-      "version": "1.8.3",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
-      "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
+      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "follow-redirects": "^1.15.6",
         "form-data": "^4.0.0",
@@ -6389,7 +6868,8 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
       "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/axobject-query": {
       "version": "4.1.0",
@@ -6972,6 +7452,7 @@
       "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
       "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
       "dev": true,
+      "license": "(MIT OR Apache-2.0)",
       "bin": {
         "btoa": "bin/btoa.js"
       },
@@ -7052,6 +7533,7 @@
       "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
       "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "mime-types": "^2.1.18",
         "ylru": "^1.2.0"
@@ -7814,6 +8296,7 @@
       "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz",
       "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "depd": "~2.0.0",
         "keygrip": "~1.1.0"
@@ -7981,6 +8464,7 @@
       "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz",
       "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "luxon": "^3.2.1"
       },
@@ -8455,13 +8939,15 @@
       }
     },
     "node_modules/cypress-multi-reporters": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-2.0.4.tgz",
-      "integrity": "sha512-TZKzSfo8ReU2Fuj1n90gi4Ocw1a/nh6utiq9g0wy27muq1/IjZXdR97WXkV0to2vd8NRldXt+tuKEmxQrp8LDg==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-2.0.5.tgz",
+      "integrity": "sha512-5ReXlNE7C/9/rpDI3z0tAJbPXsTHK7P3ogvUtBntQlmctRQ+sSMts7dIQY5MTb0XfBSge3CuwvNvaoqtw90KSQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "debug": "^4.3.7",
-        "lodash": "^4.17.21"
+        "debug": "^4.4.0",
+        "lodash": "^4.17.21",
+        "semver": "^7.6.3"
       },
       "engines": {
         "node": ">=6.0.0"
@@ -8470,6 +8956,19 @@
         "mocha": ">=3.1.2"
       }
     },
+    "node_modules/cypress-multi-reporters/node_modules/semver": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+      "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/cypress/node_modules/bluebird": {
       "version": "3.7.2",
       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -8597,6 +9096,7 @@
       "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz",
       "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=4.0"
       }
@@ -8678,7 +9178,8 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
       "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/deep-extend": {
       "version": "0.6.0",
@@ -8814,7 +9315,8 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
       "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/depd": {
       "version": "2.0.0",
@@ -9096,9 +9598,9 @@
       }
     },
     "node_modules/dotenv": {
-      "version": "16.4.7",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
-      "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
+      "version": "16.5.0",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz",
+      "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
       "dev": true,
       "license": "BSD-2-Clause",
       "engines": {
@@ -9531,6 +10033,44 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/esbuild": {
+      "version": "0.17.19",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
+      "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/android-arm": "0.17.19",
+        "@esbuild/android-arm64": "0.17.19",
+        "@esbuild/android-x64": "0.17.19",
+        "@esbuild/darwin-arm64": "0.17.19",
+        "@esbuild/darwin-x64": "0.17.19",
+        "@esbuild/freebsd-arm64": "0.17.19",
+        "@esbuild/freebsd-x64": "0.17.19",
+        "@esbuild/linux-arm": "0.17.19",
+        "@esbuild/linux-arm64": "0.17.19",
+        "@esbuild/linux-ia32": "0.17.19",
+        "@esbuild/linux-loong64": "0.17.19",
+        "@esbuild/linux-mips64el": "0.17.19",
+        "@esbuild/linux-ppc64": "0.17.19",
+        "@esbuild/linux-riscv64": "0.17.19",
+        "@esbuild/linux-s390x": "0.17.19",
+        "@esbuild/linux-x64": "0.17.19",
+        "@esbuild/netbsd-x64": "0.17.19",
+        "@esbuild/openbsd-x64": "0.17.19",
+        "@esbuild/sunos-x64": "0.17.19",
+        "@esbuild/win32-arm64": "0.17.19",
+        "@esbuild/win32-ia32": "0.17.19",
+        "@esbuild/win32-x64": "0.17.19"
+      }
+    },
     "node_modules/escalade": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -10329,6 +10869,7 @@
       "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
       "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "homedir-polyfill": "^1.0.1"
       },
@@ -10839,6 +11380,7 @@
       "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-2.0.1.tgz",
       "integrity": "sha512-qVdaUhYO39zmh28/JLQM5CoYN9byEOKEH4qfa8K1eNV17W0UUMJ9WgbR/hHFH+t5rcl+6RTb5UC7ck/I+uRkpQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "resolve-dir": "^1.0.1"
       },
@@ -10851,6 +11393,7 @@
       "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-2.0.0.tgz",
       "integrity": "sha512-WgZ+nKbELDa6N3i/9nrHeNznm+lY3z4YfhDDWgW+5P0pdmMj26bxaxU11ookgY3NyP9GC7HvZ9etp0jRFqGEeQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "find-file-up": "^2.0.1"
       },
@@ -11515,6 +12058,7 @@
       "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
       "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "global-prefix": "^1.0.1",
         "is-windows": "^1.0.1",
@@ -11529,6 +12073,7 @@
       "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
       "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "expand-tilde": "^2.0.2",
         "homedir-polyfill": "^1.0.1",
@@ -11544,13 +12089,15 @@
       "version": "1.3.8",
       "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
       "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
-      "dev": true
+      "dev": true,
+      "license": "ISC"
     },
     "node_modules/global-prefix/node_modules/which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
       "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
       "dev": true,
+      "license": "ISC",
       "dependencies": {
         "isexe": "^2.0.0"
       },
@@ -11797,6 +12344,7 @@
       "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
       "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "parse-passwd": "^1.0.0"
       },
@@ -12000,6 +12548,7 @@
       "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
       "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "deep-equal": "~1.0.1",
         "http-errors": "~1.8.0"
@@ -12013,6 +12562,7 @@
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
       "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 0.6"
       }
@@ -12022,6 +12572,7 @@
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
       "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "depd": "~1.1.2",
         "inherits": "2.0.4",
@@ -12038,6 +12589,7 @@
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
       "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 0.6"
       }
@@ -13167,6 +13719,7 @@
       "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
       "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==",
       "dev": true,
+      "license": "MIT",
       "peerDependencies": {
         "ws": "*"
       }
@@ -14565,13 +15118,13 @@
       }
     },
     "node_modules/junit-report-merger": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/junit-report-merger/-/junit-report-merger-7.0.0.tgz",
-      "integrity": "sha512-i7IYPpwVFpju+UKdxYIG9UTMb6NjfRGzWzE/lRExdEf4K3agqXtVBnJWhL9aMM2lNX7uWW/rhVidiDBsG4n5cw==",
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/junit-report-merger/-/junit-report-merger-7.0.1.tgz",
+      "integrity": "sha512-jNmdXAu0zkpXB9xIVMRocVoMvMm38esLZogDI42pFwEgANFzOgy7QC6DNewGek8SAqmsGWCCfq/koTZkjZHVZA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "commander": "~12.0.0",
+        "commander": "~12.1.0",
         "fast-glob": "~3.3.0",
         "xmlbuilder2": "3.1.1"
       },
@@ -14584,9 +15137,9 @@
       }
     },
     "node_modules/junit-report-merger/node_modules/commander": {
-      "version": "12.0.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz",
-      "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==",
+      "version": "12.1.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+      "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -14611,6 +15164,7 @@
       "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
       "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "tsscmp": "1.0.6"
       },
@@ -14649,10 +15203,11 @@
       }
     },
     "node_modules/koa": {
-      "version": "2.15.4",
-      "resolved": "https://registry.npmjs.org/koa/-/koa-2.15.4.tgz",
-      "integrity": "sha512-7fNBIdrU2PEgLljXoPWoyY4r1e+ToWCmzS/wwMPbUNs7X+5MMET1ObhJBlUkF5uZG9B6QhM2zS1TsH6adegkiQ==",
+      "version": "2.16.1",
+      "resolved": "https://registry.npmjs.org/koa/-/koa-2.16.1.tgz",
+      "integrity": "sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "accepts": "^1.3.5",
         "cache-content-type": "^1.0.0",
@@ -14686,13 +15241,15 @@
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
       "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/koa-convert": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz",
       "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "co": "^4.6.0",
         "koa-compose": "^4.1.0"
@@ -14706,6 +15263,7 @@
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 0.8"
       }
@@ -14715,6 +15273,7 @@
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
       "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "depd": "~1.1.2",
         "inherits": "2.0.4",
@@ -14731,6 +15290,7 @@
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
       "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 0.6"
       }
@@ -14740,6 +15300,7 @@
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
       "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 0.6"
       }
@@ -14959,7 +15520,8 @@
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz",
       "integrity": "sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/lodash.debounce": {
       "version": "4.0.8",
@@ -15105,6 +15667,7 @@
       "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz",
       "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==",
       "dev": true,
+      "license": "Apache-2.0",
       "dependencies": {
         "date-format": "^4.0.14",
         "debug": "^4.3.4",
@@ -15120,7 +15683,8 @@
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz",
       "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/loose-envify": {
       "version": "1.4.0",
@@ -15155,10 +15719,11 @@
       }
     },
     "node_modules/luxon": {
-      "version": "3.5.0",
-      "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz",
-      "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==",
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.6.1.tgz",
+      "integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=12"
       }
@@ -15941,6 +16506,7 @@
       "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz",
       "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "cron-parser": "^4.2.0",
         "long-timeout": "0.1.1",
@@ -16930,6 +17496,7 @@
       "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
       "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -18057,7 +18624,8 @@
       "version": "9.4.2",
       "resolved": "https://registry.npmjs.org/rambda/-/rambda-9.4.2.tgz",
       "integrity": "sha512-++euMfxnl7OgaEKwXh9QqThOjMeta2HH001N1v4mYQzBjJBnmXBh2BCK6dZAbICFVXOFUVD3xFG0R3ZPU0mxXw==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/randombytes": {
       "version": "2.1.0",
@@ -18667,6 +19235,7 @@
       "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
       "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "expand-tilde": "^2.0.0",
         "global-modules": "^1.0.0"
@@ -18746,6 +19315,15 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/rslog": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/rslog/-/rslog-1.2.3.tgz",
+      "integrity": "sha512-antALPJaKBRPBU1X2q9t085K4htWDOOv/K1qhTUk7h0l1ePU/KbDqKJn19eKP0dk7PqMioeA0+fu3gyPXCsXxQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.17.6"
+      }
+    },
     "node_modules/run-applescript": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz",
@@ -19643,7 +20221,8 @@
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz",
       "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/source-map": {
       "version": "0.5.7",
@@ -19900,6 +20479,7 @@
       "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz",
       "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "date-format": "^4.0.14",
         "debug": "^4.3.4",
@@ -19914,6 +20494,7 @@
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
       "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "graceful-fs": "^4.2.0",
         "jsonfile": "^4.0.0",
@@ -19928,6 +20509,7 @@
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
       "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
       "dev": true,
+      "license": "MIT",
       "optionalDependencies": {
         "graceful-fs": "^4.1.6"
       }
@@ -19937,6 +20519,7 @@
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
       "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 4.0.0"
       }
@@ -21071,6 +21654,7 @@
       "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
       "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=0.6.x"
       }
@@ -22501,6 +23085,7 @@
       "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz",
       "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 4.0.0"
       }
diff --git a/clients/ui/frontend/package.json b/clients/ui/frontend/package.json
index de5c211b..50ae384c 100644
--- a/clients/ui/frontend/package.json
+++ b/clients/ui/frontend/package.json
@@ -34,8 +34,8 @@
     "@babel/preset-env": "^7.26.9",
     "@babel/preset-react": "^7.18.6",
     "@babel/preset-typescript": "^7.21.5",
-    "@cypress/code-coverage": "^3.13.12",
-    "@module-federation/enhanced": "^0.11.1",
+    "@cypress/code-coverage": "^3.14.1",
+    "@module-federation/enhanced": "^0.13.1",
     "@mui/icons-material": "^6.4.8",
     "@mui/material": "^6.1.7",
     "@mui/types": "^7.2.20",
@@ -61,8 +61,8 @@
     "cypress-axe": "^1.5.0",
     "cypress-high-resolution": "^1.0.0",
     "cypress-mochawesome-reporter": "^3.8.2",
-    "cypress-multi-reporters": "^2.0.4",
-    "dotenv": "^16.4.7",
+    "cypress-multi-reporters": "^2.0.5",
+    "dotenv": "^16.5.0",
     "dotenv-expand": "^5.1.0",
     "dotenv-webpack": "^6.0.0",
     "expect": "^29.7.0",
@@ -72,7 +72,7 @@
     "imagemin": "^9.0.0",
     "jest": "^29.7.0",
     "jest-environment-jsdom": "^29.7.0",
-    "junit-report-merger": "^7.0.0",
+    "junit-report-merger": "^7.0.1",
     "mini-css-extract-plugin": "^2.9.0",
     "postcss": "^8.4.49",
     "prettier": "^3.3.3",
diff --git a/cmd/proxy.go b/cmd/proxy.go
index da46e5ca..c4992b59 100644
--- a/cmd/proxy.go
+++ b/cmd/proxy.go
@@ -123,5 +123,8 @@ func init() {
 	proxyCmd.Flags().StringVar(&proxyCfg.Datastore.MLMD.Hostname, "mlmd-hostname", proxyCfg.Datastore.MLMD.Hostname, "MLMD hostname")
 	proxyCmd.Flags().IntVar(&proxyCfg.Datastore.MLMD.Port, "mlmd-port", proxyCfg.Datastore.MLMD.Port, "MLMD port")
 
+	proxyCmd.Flags().StringVar(&proxyCfg.Datastore.EmbedMD.DatabaseType, "embedmd-database-type", "mysql", "EmbedMD database type")
+	proxyCmd.Flags().StringVar(&proxyCfg.Datastore.EmbedMD.DatabaseDSN, "embedmd-database-dsn", "", "EmbedMD database DSN")
+
 	proxyCmd.Flags().StringVar(&proxyCfg.Datastore.Type, "datastore-type", proxyCfg.Datastore.Type, "Datastore type")
 }
diff --git a/go.mod b/go.mod
index 72a2b69e..e34a18b9 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@ require (
 	github.com/go-chi/chi/v5 v5.2.1
 	github.com/go-chi/cors v1.2.1
 	github.com/go-logr/logr v1.4.2
+	github.com/golang-migrate/migrate/v4 v4.18.3
 	github.com/golang/glog v1.2.5
 	github.com/kserve/kserve v0.15.0
 	github.com/onsi/ginkgo v1.16.5
@@ -16,9 +17,12 @@ require (
 	github.com/spf13/viper v1.20.1
 	github.com/stretchr/testify v1.10.0
 	github.com/testcontainers/testcontainers-go v0.37.0
+	github.com/testcontainers/testcontainers-go/modules/mysql v0.37.0
 	go.uber.org/zap v1.27.0
-	google.golang.org/grpc v1.72.0
+	google.golang.org/grpc v1.72.1
 	google.golang.org/protobuf v1.36.6
+	gorm.io/driver/mysql v1.5.7
+	gorm.io/gorm v1.25.7
 	k8s.io/api v0.32.3
 	k8s.io/apimachinery v0.32.3
 	k8s.io/client-go v0.32.3
@@ -63,6 +67,7 @@ require (
 	github.com/go-openapi/swag v0.23.1 // indirect
 	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-sql-driver/mysql v1.7.1 // indirect
 	github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
 	github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
 	github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
@@ -79,6 +84,10 @@ require (
 	github.com/googleapis/gax-go/v2 v2.14.1 // indirect
 	github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720 // indirect
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
+	github.com/hashicorp/errwrap v1.1.0 // indirect
+	github.com/hashicorp/go-multierror v1.1.1 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
 	github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
@@ -107,13 +116,14 @@ require (
 	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect
 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
 	go.opentelemetry.io/otel v1.35.0 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
 	go.opentelemetry.io/otel/metric v1.35.0 // indirect
 	go.opentelemetry.io/otel/sdk v1.35.0 // indirect
 	go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
 	go.opentelemetry.io/otel/trace v1.35.0 // indirect
 	go.opentelemetry.io/proto/otlp v1.3.1 // indirect
+	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/automaxprocs v1.6.0 // indirect
 	golang.org/x/crypto v0.37.0 // indirect
 	golang.org/x/oauth2 v0.29.0 // indirect
diff --git a/go.sum b/go.sum
index 9205e051..b0828e5d 100644
--- a/go.sum
+++ b/go.sum
@@ -86,6 +86,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dhui/dktest v0.4.5 h1:uUfYBIVREmj/Rw6MvgmqNAYzTiKOHJak+enB5Di73MM=
+github.com/dhui/dktest v0.4.5/go.mod h1:tmcyeHDKagvlDrz7gDKq4UAJOLIfVZYkfD5OnHDwcCo=
 github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
 github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
 github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0=
@@ -153,6 +155,9 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
 github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
@@ -160,6 +165,8 @@ github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIx
 github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
+github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I=
 github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
@@ -228,11 +235,20 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720
 github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY=
 github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@@ -256,6 +272,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
 github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
 github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
+github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
+github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
 github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
 github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
@@ -367,6 +385,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
 github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg=
 github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM=
+github.com/testcontainers/testcontainers-go/modules/mysql v0.37.0 h1:LqUos1oR5iuuzorFnSvxsHNdYdCHB/DfI82CuT58wbI=
+github.com/testcontainers/testcontainers-go/modules/mysql v0.37.0/go.mod h1:vHEEHx5Kf+uq5hveaVAMrTzPY8eeRZcKcl23MRw5Tkc=
 github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
 github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
 github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -393,8 +413,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRND
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
 go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
 go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
@@ -412,6 +432,8 @@ go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J
 go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
 go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
+go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
 go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -563,8 +585,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
-google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
+google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
+google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -599,6 +621,10 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
+gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
 gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
 gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/internal/datastore/connector.go b/internal/datastore/connector.go
index 9d02eee3..8c75de37 100644
--- a/internal/datastore/connector.go
+++ b/internal/datastore/connector.go
@@ -4,6 +4,8 @@ import (
 	"errors"
 	"fmt"
 
+	"github.com/kubeflow/model-registry/internal/datastore/embedmd"
+	"github.com/kubeflow/model-registry/internal/datastore/mlmd"
 	"github.com/kubeflow/model-registry/pkg/api"
 )
 
@@ -15,8 +17,9 @@ var (
 type TeardownFunc func() error
 
 type Datastore struct {
-	MLMD MLMDConfig
-	Type string
+	MLMD    mlmd.MLMDConfig
+	EmbedMD embedmd.EmbedMDConfig
+	Type    string
 }
 
 type Connector interface {
@@ -31,10 +34,21 @@ func NewConnector(ds Datastore) (Connector, error) {
 			return nil, fmt.Errorf("invalid MLMD config: %w", err)
 		}
 
-		mlmd := NewMLMDService(&ds.MLMD)
+		mlmd := mlmd.NewMLMDService(&ds.MLMD)
 
 		return mlmd, nil
+	case "embedmd":
+		if err := ds.EmbedMD.Validate(); err != nil {
+			return nil, fmt.Errorf("invalid EmbedMD config: %w", err)
+		}
+
+		embedmd, err := embedmd.NewEmbedMDService(&ds.EmbedMD)
+		if err != nil {
+			return nil, fmt.Errorf("error creating EmbedMD service: %w", err)
+		}
+
+		return embedmd, nil
 	default:
-		return nil, fmt.Errorf("%w: %s. Supported types: mlmd", ErrUnsupportedDatastore, ds.Type)
+		return nil, fmt.Errorf("%w: %s. Supported types: mlmd, embedmd", ErrUnsupportedDatastore, ds.Type)
 	}
 }
diff --git a/internal/datastore/embedmd/mysql/connect.go b/internal/datastore/embedmd/mysql/connect.go
new file mode 100644
index 00000000..25bfc62b
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/connect.go
@@ -0,0 +1,32 @@
+package mysql
+
+import (
+	"gorm.io/driver/mysql"
+	"gorm.io/gorm"
+)
+
+type MySQLDBConnector struct {
+	DSN string
+	db  *gorm.DB
+}
+
+func NewMySQLDBConnector(dsn string) *MySQLDBConnector {
+	return &MySQLDBConnector{
+		DSN: dsn,
+	}
+}
+
+func (c *MySQLDBConnector) Connect() (*gorm.DB, error) {
+	db, err := gorm.Open(mysql.Open(c.DSN), &gorm.Config{})
+	if err != nil {
+		return nil, err
+	}
+
+	c.db = db
+
+	return db, nil
+}
+
+func (c *MySQLDBConnector) DB() *gorm.DB {
+	return c.db
+}
diff --git a/internal/datastore/embedmd/mysql/migrate.go b/internal/datastore/embedmd/mysql/migrate.go
new file mode 100644
index 00000000..d7f24454
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrate.go
@@ -0,0 +1,86 @@
+package mysql
+
+import (
+	"embed"
+	"fmt"
+
+	"github.com/golang-migrate/migrate/v4"
+	"github.com/golang-migrate/migrate/v4/database/mysql"
+	"github.com/golang-migrate/migrate/v4/source/iofs"
+	"gorm.io/gorm"
+)
+
+//go:embed migrations/*.sql
+var migrations embed.FS
+
+const (
+	MigrationDir = "migrations"
+)
+
+type MySQLMigrator struct {
+	migrator *migrate.Migrate
+}
+
+func NewMySQLMigrator(db *gorm.DB) (*MySQLMigrator, error) {
+	sqlDB, err := db.DB()
+	if err != nil {
+		return nil, err
+	}
+
+	driver, err := mysql.WithInstance(sqlDB, &mysql.Config{})
+	if err != nil {
+		return nil, err
+	}
+
+	// Create a new source instance from the embedded files
+	source, err := iofs.New(migrations, MigrationDir)
+	if err != nil {
+		return nil, err
+	}
+
+	m, err := migrate.NewWithInstance(
+		"iofs",
+		source,
+		"mysql",
+		driver,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	return &MySQLMigrator{
+		migrator: m,
+	}, nil
+}
+
+func (m *MySQLMigrator) Migrate() error {
+	if err := m.Up(nil); err != nil && err != migrate.ErrNoChange {
+		return err
+	}
+
+	return nil
+}
+
+func (m *MySQLMigrator) Up(steps *int) error {
+	if steps == nil {
+		return m.migrator.Up()
+	}
+
+	if *steps < 0 {
+		return fmt.Errorf("steps cannot be negative")
+	}
+
+	return m.migrator.Steps(*steps)
+}
+
+func (m *MySQLMigrator) Down(steps *int) error {
+	if steps == nil {
+		return m.migrator.Down()
+	}
+
+	if *steps > 0 {
+		return fmt.Errorf("steps cannot be positive")
+	}
+
+	return m.migrator.Steps(*steps)
+}
diff --git a/internal/datastore/embedmd/mysql/migrations/000001_create_artifact_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000001_create_artifact_table.down.sql
new file mode 100644
index 00000000..f3de9be4
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000001_create_artifact_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `Artifact`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000001_create_artifact_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000001_create_artifact_table.up.sql
new file mode 100644
index 00000000..a3e5bfb0
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000001_create_artifact_table.up.sql
@@ -0,0 +1,17 @@
+CREATE TABLE IF NOT EXISTS `Artifact` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `type_id` int NOT NULL,
+  `uri` text,
+  `state` int DEFAULT NULL,
+  `name` varchar(255) DEFAULT NULL,
+  `external_id` varchar(255) DEFAULT NULL,
+  `create_time_since_epoch` bigint NOT NULL DEFAULT '0',
+  `last_update_time_since_epoch` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `external_id` (`external_id`),
+  UNIQUE KEY `UniqueArtifactTypeName` (`type_id`,`name`),
+  KEY `idx_artifact_uri` (`uri`(255)),
+  KEY `idx_artifact_create_time_since_epoch` (`create_time_since_epoch`),
+  KEY `idx_artifact_last_update_time_since_epoch` (`last_update_time_since_epoch`),
+  KEY `idx_artifact_external_id` (`external_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000002_create_artifactproperty_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000002_create_artifactproperty_table.down.sql
new file mode 100644
index 00000000..5b11b162
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000002_create_artifactproperty_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `ArtifactProperty`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000002_create_artifactproperty_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000002_create_artifactproperty_table.up.sql
new file mode 100644
index 00000000..ea8cfd63
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000002_create_artifactproperty_table.up.sql
@@ -0,0 +1,15 @@
+CREATE TABLE IF NOT EXISTS `ArtifactProperty` (
+  `artifact_id` int NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `is_custom_property` tinyint(1) NOT NULL,
+  `int_value` int DEFAULT NULL,
+  `double_value` double DEFAULT NULL,
+  `string_value` mediumtext,
+  `byte_value` mediumblob,
+  `proto_value` mediumblob,
+  `bool_value` tinyint(1) DEFAULT NULL,
+  PRIMARY KEY (`artifact_id`,`name`,`is_custom_property`),
+  KEY `idx_artifact_property_int` (`name`,`is_custom_property`,`int_value`),
+  KEY `idx_artifact_property_double` (`name`,`is_custom_property`,`double_value`),
+  KEY `idx_artifact_property_string` (`name`,`is_custom_property`,`string_value`(255))
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000003_create_association_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000003_create_association_table.down.sql
new file mode 100644
index 00000000..4c37ffa1
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000003_create_association_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `Association`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000003_create_association_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000003_create_association_table.up.sql
new file mode 100644
index 00000000..b45e65ba
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000003_create_association_table.up.sql
@@ -0,0 +1,7 @@
+CREATE TABLE IF NOT EXISTS `Association` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `context_id` int NOT NULL,
+  `execution_id` int NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `context_id` (`context_id`,`execution_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000004_create_attribution_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000004_create_attribution_table.down.sql
new file mode 100644
index 00000000..77a67628
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000004_create_attribution_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `Attribution`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000004_create_attribution_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000004_create_attribution_table.up.sql
new file mode 100644
index 00000000..a51e5018
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000004_create_attribution_table.up.sql
@@ -0,0 +1,7 @@
+CREATE TABLE IF NOT EXISTS `Attribution` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `context_id` int NOT NULL,
+  `artifact_id` int NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `context_id` (`context_id`,`artifact_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000005_create_context_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000005_create_context_table.down.sql
new file mode 100644
index 00000000..0aec534f
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000005_create_context_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `Context`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000005_create_context_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000005_create_context_table.up.sql
new file mode 100644
index 00000000..f8f7063d
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000005_create_context_table.up.sql
@@ -0,0 +1,14 @@
+CREATE TABLE IF NOT EXISTS `Context` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `type_id` int NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `external_id` varchar(255) DEFAULT NULL,
+  `create_time_since_epoch` bigint NOT NULL DEFAULT '0',
+  `last_update_time_since_epoch` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `type_id` (`type_id`,`name`),
+  UNIQUE KEY `external_id` (`external_id`),
+  KEY `idx_context_create_time_since_epoch` (`create_time_since_epoch`),
+  KEY `idx_context_last_update_time_since_epoch` (`last_update_time_since_epoch`),
+  KEY `idx_context_external_id` (`external_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000006_create_contextproperty_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000006_create_contextproperty_table.down.sql
new file mode 100644
index 00000000..15618a16
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000006_create_contextproperty_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `ContextProperty`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000006_create_contextproperty_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000006_create_contextproperty_table.up.sql
new file mode 100644
index 00000000..103f58ab
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000006_create_contextproperty_table.up.sql
@@ -0,0 +1,15 @@
+CREATE TABLE IF NOT EXISTS `ContextProperty` (
+  `context_id` int NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `is_custom_property` tinyint(1) NOT NULL,
+  `int_value` int DEFAULT NULL,
+  `double_value` double DEFAULT NULL,
+  `string_value` mediumtext,
+  `byte_value` mediumblob,
+  `proto_value` mediumblob,
+  `bool_value` tinyint(1) DEFAULT NULL,
+  PRIMARY KEY (`context_id`,`name`,`is_custom_property`),
+  KEY `idx_context_property_int` (`name`,`is_custom_property`,`int_value`),
+  KEY `idx_context_property_double` (`name`,`is_custom_property`,`double_value`),
+  KEY `idx_context_property_string` (`name`,`is_custom_property`,`string_value`(255))
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000007_create_event_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000007_create_event_table.down.sql
new file mode 100644
index 00000000..c526b783
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000007_create_event_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `Event`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000007_create_event_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000007_create_event_table.up.sql
new file mode 100644
index 00000000..74a8699f
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000007_create_event_table.up.sql
@@ -0,0 +1,10 @@
+CREATE TABLE IF NOT EXISTS `Event` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `artifact_id` int NOT NULL,
+  `execution_id` int NOT NULL,
+  `type` int NOT NULL,
+  `milliseconds_since_epoch` bigint DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `UniqueEvent` (`artifact_id`,`execution_id`,`type`),
+  KEY `idx_event_execution_id` (`execution_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000008_create_eventpath_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000008_create_eventpath_table.down.sql
new file mode 100644
index 00000000..955c9bda
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000008_create_eventpath_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `EventPath`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000008_create_eventpath_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000008_create_eventpath_table.up.sql
new file mode 100644
index 00000000..07bb5e5a
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000008_create_eventpath_table.up.sql
@@ -0,0 +1,7 @@
+CREATE TABLE IF NOT EXISTS `EventPath` (
+  `event_id` int NOT NULL,
+  `is_index_step` tinyint(1) NOT NULL,
+  `step_index` int DEFAULT NULL,
+  `step_key` text,
+  KEY `idx_eventpath_event_id` (`event_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000009_create_execution_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000009_create_execution_table.down.sql
new file mode 100644
index 00000000..c3ff8927
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000009_create_execution_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `Execution`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000009_create_execution_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000009_create_execution_table.up.sql
new file mode 100644
index 00000000..ec6b0567
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000009_create_execution_table.up.sql
@@ -0,0 +1,15 @@
+CREATE TABLE IF NOT EXISTS `Execution` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `type_id` int NOT NULL,
+  `last_known_state` int DEFAULT NULL,
+  `name` varchar(255) DEFAULT NULL,
+  `external_id` varchar(255) DEFAULT NULL,
+  `create_time_since_epoch` bigint NOT NULL DEFAULT '0',
+  `last_update_time_since_epoch` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `external_id` (`external_id`),
+  UNIQUE KEY `UniqueExecutionTypeName` (`type_id`,`name`),
+  KEY `idx_execution_create_time_since_epoch` (`create_time_since_epoch`),
+  KEY `idx_execution_last_update_time_since_epoch` (`last_update_time_since_epoch`),
+  KEY `idx_execution_external_id` (`external_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000010_create_executionproperty_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000010_create_executionproperty_table.down.sql
new file mode 100644
index 00000000..37c80fd8
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000010_create_executionproperty_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `ExecutionProperty`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000010_create_executionproperty_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000010_create_executionproperty_table.up.sql
new file mode 100644
index 00000000..3a64bdbc
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000010_create_executionproperty_table.up.sql
@@ -0,0 +1,15 @@
+CREATE TABLE IF NOT EXISTS `ExecutionProperty` (
+  `execution_id` int NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `is_custom_property` tinyint(1) NOT NULL,
+  `int_value` int DEFAULT NULL,
+  `double_value` double DEFAULT NULL,
+  `string_value` mediumtext,
+  `byte_value` mediumblob,
+  `proto_value` mediumblob,
+  `bool_value` tinyint(1) DEFAULT NULL,
+  PRIMARY KEY (`execution_id`,`name`,`is_custom_property`),
+  KEY `idx_execution_property_int` (`name`,`is_custom_property`,`int_value`),
+  KEY `idx_execution_property_double` (`name`,`is_custom_property`,`double_value`),
+  KEY `idx_execution_property_string` (`name`,`is_custom_property`,`string_value`(255))
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000011_create_mlmdenv_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000011_create_mlmdenv_table.down.sql
new file mode 100644
index 00000000..e189b155
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000011_create_mlmdenv_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `MLMDEnv`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000011_create_mlmdenv_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000011_create_mlmdenv_table.up.sql
new file mode 100644
index 00000000..66640e07
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000011_create_mlmdenv_table.up.sql
@@ -0,0 +1,4 @@
+CREATE TABLE IF NOT EXISTS `MLMDEnv` (
+  `schema_version` int NOT NULL,
+  PRIMARY KEY (`schema_version`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000012_create_parentcontext_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000012_create_parentcontext_table.down.sql
new file mode 100644
index 00000000..17ccb18d
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000012_create_parentcontext_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `ParentContext`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000012_create_parentcontext_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000012_create_parentcontext_table.up.sql
new file mode 100644
index 00000000..6c7c1c67
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000012_create_parentcontext_table.up.sql
@@ -0,0 +1,6 @@
+CREATE TABLE IF NOT EXISTS `ParentContext` (
+  `context_id` int NOT NULL,
+  `parent_context_id` int NOT NULL,
+  PRIMARY KEY (`context_id`,`parent_context_id`),
+  KEY `idx_parentcontext_parent_context_id` (`parent_context_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000013_create_parenttype_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000013_create_parenttype_table.down.sql
new file mode 100644
index 00000000..3ca7a901
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000013_create_parenttype_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `ParentType`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000013_create_parenttype_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000013_create_parenttype_table.up.sql
new file mode 100644
index 00000000..81fecc76
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000013_create_parenttype_table.up.sql
@@ -0,0 +1,5 @@
+CREATE TABLE IF NOT EXISTS `ParentType` (
+  `type_id` int NOT NULL,
+  `parent_type_id` int NOT NULL,
+  PRIMARY KEY (`type_id`,`parent_type_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000014_create_type_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000014_create_type_table.down.sql
new file mode 100644
index 00000000..bee398fe
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000014_create_type_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `Type`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000014_create_type_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000014_create_type_table.up.sql
new file mode 100644
index 00000000..32387731
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000014_create_type_table.up.sql
@@ -0,0 +1,14 @@
+CREATE TABLE IF NOT EXISTS `Type` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) NOT NULL,
+  `version` varchar(255) DEFAULT NULL,
+  `type_kind` tinyint(1) NOT NULL,
+  `description` text,
+  `input_type` text,
+  `output_type` text,
+  `external_id` varchar(255) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `external_id` (`external_id`),
+  KEY `idx_type_name` (`name`),
+  KEY `idx_type_external_id` (`external_id`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000015_create_typeproperty_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000015_create_typeproperty_table.down.sql
new file mode 100644
index 00000000..e7710889
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000015_create_typeproperty_table.down.sql
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS `TypeProperty`;
diff --git a/internal/datastore/embedmd/mysql/migrations/000015_create_typeproperty_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000015_create_typeproperty_table.up.sql
new file mode 100644
index 00000000..1f7f4cdf
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000015_create_typeproperty_table.up.sql
@@ -0,0 +1,6 @@
+CREATE TABLE IF NOT EXISTS `TypeProperty` (
+  `type_id` int NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `data_type` int DEFAULT NULL,
+  PRIMARY KEY (`type_id`,`name`)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000016_seed_type_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000016_seed_type_table.down.sql
new file mode 100644
index 00000000..6b891c78
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000016_seed_type_table.down.sql
@@ -0,0 +1,18 @@
+DELETE FROM `Type` WHERE `name` IN (
+    'mlmd.Dataset',
+    'mlmd.Model',
+    'mlmd.Metrics',
+    'mlmd.Statistics',
+    'mlmd.Train',
+    'mlmd.Transform',
+    'mlmd.Process',
+    'mlmd.Evaluate',
+    'mlmd.Deploy',
+    'kf.RegisteredModel',
+    'kf.ModelVersion',
+    'kf.DocArtifact',
+    'kf.ModelArtifact',
+    'kf.ServingEnvironment',
+    'kf.InferenceService',
+    'kf.ServeModel'
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000016_seed_type_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000016_seed_type_table.up.sql
new file mode 100644
index 00000000..ca1bd9d1
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000016_seed_type_table.up.sql
@@ -0,0 +1,23 @@
+INSERT INTO `Type` (`name`, `version`, `type_kind`, `description`, `input_type`, `output_type`, `external_id`)
+SELECT t.* FROM (
+    SELECT 'mlmd.Dataset' as name, NULL as version, 1 as type_kind, NULL as description, NULL as input_type, NULL as output_type, NULL as external_id
+    UNION ALL SELECT 'mlmd.Model', NULL, 1, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'mlmd.Metrics', NULL, 1, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'mlmd.Statistics', NULL, 1, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'mlmd.Train', NULL, 0, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'mlmd.Transform', NULL, 0, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'mlmd.Process', NULL, 0, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'mlmd.Evaluate', NULL, 0, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'mlmd.Deploy', NULL, 0, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'kf.RegisteredModel', NULL, 2, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'kf.ModelVersion', NULL, 2, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'kf.DocArtifact', NULL, 1, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'kf.ModelArtifact', NULL, 1, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'kf.ServingEnvironment', NULL, 2, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'kf.InferenceService', NULL, 2, NULL, NULL, NULL, NULL
+    UNION ALL SELECT 'kf.ServeModel', NULL, 0, NULL, NULL, NULL, NULL
+) t
+WHERE NOT EXISTS (
+    SELECT 1 FROM `Type`
+    WHERE `name` = t.name AND `version` IS NULL
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000017_seed_typeproperty_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000017_seed_typeproperty_table.down.sql
new file mode 100644
index 00000000..b97efdfa
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000017_seed_typeproperty_table.down.sql
@@ -0,0 +1,27 @@
+DELETE FROM `TypeProperty`
+WHERE (`type_id`, `name`, `data_type`) IN (
+    ((SELECT id FROM `Type` WHERE name = 'kf.RegisteredModel'), 'description', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.RegisteredModel'), 'owner', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.RegisteredModel'), 'state', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'author', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'description', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'model_name', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'state', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'version', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.DocArtifact'), 'description', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'description', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'model_format_name', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'model_format_version', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'service_account_name', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'storage_key', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'storage_path', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ServingEnvironment'), 'description', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'description', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'desired_state', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'model_version_id', 1),
+    ((SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'registered_model_id', 1),
+    ((SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'runtime', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'serving_environment_id', 1),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ServeModel'), 'description', 3),
+    ((SELECT id FROM `Type` WHERE name = 'kf.ServeModel'), 'model_version_id', 1)
+);
diff --git a/internal/datastore/embedmd/mysql/migrations/000017_seed_typeproperty_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000017_seed_typeproperty_table.up.sql
new file mode 100644
index 00000000..a662f1c2
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000017_seed_typeproperty_table.up.sql
@@ -0,0 +1,25 @@
+INSERT IGNORE INTO `TypeProperty` (`type_id`, `name`, `data_type`)
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.RegisteredModel'), 'description', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.RegisteredModel'), 'owner', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.RegisteredModel'), 'state', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'author', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'description', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'model_name', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'state', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelVersion'), 'version', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.DocArtifact'), 'description', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'description', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'model_format_name', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'model_format_version', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'service_account_name', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'storage_key', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ModelArtifact'), 'storage_path', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ServingEnvironment'), 'description', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'description', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'desired_state', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'model_version_id', 1 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'registered_model_id', 1 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'runtime', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.InferenceService'), 'serving_environment_id', 1 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ServeModel'), 'description', 3 UNION ALL
+SELECT (SELECT id FROM `Type` WHERE name = 'kf.ServeModel'), 'model_version_id', 1;
diff --git a/internal/datastore/embedmd/mysql/migrations/000018_seed_mlmdenv_table.down.sql b/internal/datastore/embedmd/mysql/migrations/000018_seed_mlmdenv_table.down.sql
new file mode 100644
index 00000000..625b1f39
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000018_seed_mlmdenv_table.down.sql
@@ -0,0 +1 @@
+DELETE FROM `MLMDEnv` WHERE `schema_version` = 10;
diff --git a/internal/datastore/embedmd/mysql/migrations/000018_seed_mlmdenv_table.up.sql b/internal/datastore/embedmd/mysql/migrations/000018_seed_mlmdenv_table.up.sql
new file mode 100644
index 00000000..08ca3f61
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrations/000018_seed_mlmdenv_table.up.sql
@@ -0,0 +1,2 @@
+INSERT IGNORE INTO `MLMDEnv` (`schema_version`) VALUES
+(10);
diff --git a/internal/datastore/embedmd/service.go b/internal/datastore/embedmd/service.go
new file mode 100644
index 00000000..d3824c0f
--- /dev/null
+++ b/internal/datastore/embedmd/service.go
@@ -0,0 +1,65 @@
+package embedmd
+
+import (
+	"fmt"
+
+	"github.com/kubeflow/model-registry/internal/db"
+	"github.com/kubeflow/model-registry/pkg/api"
+)
+
+const (
+	DatabaseTypeMySQL = "mysql"
+)
+
+type EmbedMDConfig struct {
+	DatabaseType string
+	DatabaseDSN  string
+}
+
+func (c *EmbedMDConfig) Validate() error {
+	if c.DatabaseType != DatabaseTypeMySQL {
+		return fmt.Errorf("unsupported database type: %s", c.DatabaseType)
+	}
+
+	return nil
+}
+
+type EmbedMDService struct {
+	*EmbedMDConfig
+	dbConnector db.Connector
+}
+
+func NewEmbedMDService(cfg *EmbedMDConfig) (*EmbedMDService, error) {
+	dbConnector, err := db.NewConnector(cfg.DatabaseType, cfg.DatabaseDSN)
+	if err != nil {
+		return nil, err
+	}
+
+	return &EmbedMDService{
+		EmbedMDConfig: cfg,
+		dbConnector:   dbConnector,
+	}, nil
+}
+
+func (s *EmbedMDService) Connect() (api.ModelRegistryApi, error) {
+	connectedDB, err := s.dbConnector.Connect()
+	if err != nil {
+		return nil, err
+	}
+
+	migrator, err := db.NewDBMigrator(s.DatabaseType, connectedDB)
+	if err != nil {
+		return nil, err
+	}
+
+	err = migrator.Migrate()
+	if err != nil {
+		return nil, err
+	}
+
+	return nil, nil
+}
+
+func (s *EmbedMDService) Teardown() error {
+	return nil
+}
diff --git a/internal/datastore/mlmd.go b/internal/datastore/mlmd/service.go
similarity index 99%
rename from internal/datastore/mlmd.go
rename to internal/datastore/mlmd/service.go
index e72bc7da..57a35700 100644
--- a/internal/datastore/mlmd.go
+++ b/internal/datastore/mlmd/service.go
@@ -1,4 +1,4 @@
-package datastore
+package mlmd
 
 import (
 	"errors"
diff --git a/internal/db/connector.go b/internal/db/connector.go
new file mode 100644
index 00000000..dabea20a
--- /dev/null
+++ b/internal/db/connector.go
@@ -0,0 +1,22 @@
+package db
+
+import (
+	"fmt"
+
+	"github.com/kubeflow/model-registry/internal/datastore/embedmd/mysql"
+	"gorm.io/gorm"
+)
+
+type Connector interface {
+	Connect() (*gorm.DB, error)
+	DB() *gorm.DB
+}
+
+func NewConnector(dbType string, dsn string) (Connector, error) {
+	switch dbType {
+	case "mysql":
+		return mysql.NewMySQLDBConnector(dsn), nil
+	}
+
+	return nil, fmt.Errorf("unsupported database type: %s", dbType)
+}
diff --git a/internal/db/migrator.go b/internal/db/migrator.go
new file mode 100644
index 00000000..b4ecad6e
--- /dev/null
+++ b/internal/db/migrator.go
@@ -0,0 +1,23 @@
+package db
+
+import (
+	"fmt"
+
+	"github.com/kubeflow/model-registry/internal/datastore/embedmd/mysql"
+	"gorm.io/gorm"
+)
+
+type DBMigrator interface {
+	Migrate() error
+	Up(steps *int) error
+	Down(steps *int) error
+}
+
+func NewDBMigrator(dbType string, db *gorm.DB) (DBMigrator, error) {
+	switch dbType {
+	case "mysql":
+		return mysql.NewMySQLMigrator(db)
+	}
+
+	return nil, fmt.Errorf("unsupported database type: %s", dbType)
+}
diff --git a/jobs/async-upload/.dockerignore b/jobs/async-upload/.dockerignore
new file mode 100644
index 00000000..e69de29b
diff --git a/jobs/async-upload/Dockerfile b/jobs/async-upload/Dockerfile
new file mode 100644
index 00000000..063b7c2d
--- /dev/null
+++ b/jobs/async-upload/Dockerfile
@@ -0,0 +1,50 @@
+###############################################################################
+#  Asynchronous Model-Sync Job image for Kubeflow Model Registry (https://github.com/kubeflow/model-registry/issues/1108)
+###############################################################################
+
+FROM ubi10/python-312-minimal AS base
+
+# security/env hardening
+ENV PYTHONDONTWRITEBYTECODE=1 \
+    PYTHONUNBUFFERED=1 \
+    PIP_NO_CACHE_DIR=off \
+    PIP_DISABLE_PIP_VERSION_CHECK=on
+
+# Create an unprivileged user
+RUN addgroup --system --gid 1000 app \
+    && adduser  --system --uid 1000 --ingroup app --home /app app
+
+WORKDIR /app
+
+# Copy Python dependencies first to leverage layer caching
+COPY requirements.txt .
+RUN --mount=type=cache,target=/root/.cache \
+    apt-get update && apt-get install -y --no-install-recommends ca-certificates \
+    && pip install --no-cache-dir -r requirements.txt \
+    && apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/*
+
+# Copy application source
+COPY . .
+
+# Switch to the non-root user for the final image layer
+USER 1000:1000
+
+# Add an explicit health-check (K8s will surface this in Pod.status)
+HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
+    CMD python -m job.healthcheck
+
+# OCI-recommended labels
+ARG VCS_REF=unknown
+ARG BUILD_DATE
+LABEL org.opencontainers.image.created=$BUILD_DATE \
+    org.opencontainers.image.revision=$VCS_REF \
+    org.opencontainers.image.title="Kubeflow Model Registry Async-Upload Job" \
+    org.opencontainers.image.description="K8s Job image that copies a model between storage back-ends and registers it in Kubeflow Model Registry." \
+    org.opencontainers.image.url="https://github.com/kubeflow/model-registry" \
+    org.opencontainers.image.source="https://github.com/kubeflow/model-registry/tree/main/jobs/async-upload" \
+    org.opencontainers.image.version="0.1.0" \
+    org.opencontainers.image.licenses="Apache-2.0" \
+    org.opencontainers.image.authors="Kubeflow Model Registry maintainers"
+
+# The Job controller will pass CLI flags/ENV-vars described in issue #1108.
+ENTRYPOINT ["python", "-m", "job.entrypoint"]
diff --git a/jobs/async-upload/README.md b/jobs/async-upload/README.md
new file mode 100644
index 00000000..443ed1c8
--- /dev/null
+++ b/jobs/async-upload/README.md
@@ -0,0 +1,26 @@
+# Kubeflow Model Registry – Async Upload Job
+
+> Lightweight, non‑root Python Job containerised for **transferring model artefacts** between storage back‑ends (S3, OCI, PVC, …) and registering them in **Kubeflow Model Registry**. Born out of the discussion in [kubeflow/model-registry #1108](https://github.com/kubeflow/model-registry/issues/1108).
+
+---
+
+## Quick start
+
+```bash
+# 1 – Build & tag ( reproducible build args are optional )
+docker build \
+  --build-arg VCS_REF=$(git rev-parse --short HEAD) \
+  --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
+  -t quay.io/<org>/async-upload-job:$(git rev-parse --short HEAD) .
+
+# 2 – Push to your registry
+docker push quay.io/<org>/async-upload-job:<tag>
+
+# TODO: Run locally...
+```
+
+## References
+
+- Issue thread : [https://github.com/kubeflow/model-registry/issues/1108](https://github.com/kubeflow/model-registry/issues/1108)
+- OCI Image Spec : [https://github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec)
+- Kubernetes Pod Security : [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/)
diff --git a/jobs/async-upload/job/__init__.py b/jobs/async-upload/job/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/jobs/async-upload/job/entrypoint.py b/jobs/async-upload/job/entrypoint.py
new file mode 100644
index 00000000..723e3dc7
--- /dev/null
+++ b/jobs/async-upload/job/entrypoint.py
@@ -0,0 +1,11 @@
+def main() -> None:
+    """
+    Placeholder for main entrypoint
+
+    TODO: Implement the main entrypoint
+    """
+    print("Hello, world!")
+
+
+if __name__ == "__main__":  # pragma: no cover
+    main()
diff --git a/jobs/async-upload/job/healthcheck.py b/jobs/async-upload/job/healthcheck.py
new file mode 100644
index 00000000..5ff9dd85
--- /dev/null
+++ b/jobs/async-upload/job/healthcheck.py
@@ -0,0 +1,14 @@
+import sys
+
+
+def main() -> None:
+    """
+    Placeholder for a healthcheck endpoint for the k8s api server to validate the job is still running
+
+    TODO: Implement healthchecks
+    """
+    sys.exit(0)
+
+
+if __name__ == "__main__":  # pragma: no cover
+    main()
diff --git a/jobs/async-upload/pyproject.toml b/jobs/async-upload/pyproject.toml
new file mode 100644
index 00000000..b4745dbe
--- /dev/null
+++ b/jobs/async-upload/pyproject.toml
@@ -0,0 +1,16 @@
+[project]
+name = "async-upload"
+version = "0.0.1"
+description = "Model Registry Job to upload a Model from a source to a destination"
+authors = [
+    {name = "Your Name",email = "you@example.com"}
+]
+readme = "README.md"
+requires-python = ">=3.10"
+dependencies = [
+]
+
+
+[build-system]
+requires = ["poetry-core>=2.0.0,<3.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/jobs/async-upload/requirements.txt b/jobs/async-upload/requirements.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/manifests/kustomize/README.md b/manifests/kustomize/README.md
index 6aab1c29..65d47875 100644
--- a/manifests/kustomize/README.md
+++ b/manifests/kustomize/README.md
@@ -11,26 +11,34 @@ This is the full installation guide, for a quick install in an existing Kubeflow
 
 These instructions assume that you've installed Kubeflow from the [manifests](https://github.com/kubeflow/manifests/), if you're using a distribution consult its documentation instead.
 
-Kubeflow Central Dashboard uses [Profiles](https://www.kubeflow.org/docs/components/central-dash/profiles/) to handle user namespaces and permissions. By default, the manifests deploy the Model Registry instance in the `kubeflow` namespace, to install a compatible version of Model Registry for Kubeflow, you should deploy a separate instance of Model Registry in the profile's namespace. For that just run:
+Kubeflow Central Dashboard uses [profiles](https://www.kubeflow.org/docs/components/central-dash/profiles/) to handle user namespaces and permissions. You will need to deploy Model Registry into a profile namespace.
+
+> **🛈 Note:** If you're not sure of the profile name, you can find it in the name space drop-down on the Kubeflow Dashboard.
+
+The commands in this section assume that you've defined an environment variable with the target profile namespace:
 
 ```sh
 PROFILE_NAME=<your-profile>
-for DIR in options/istio overlays/db ; do (cd $DIR; kustomize edit set namespace $PROFILE_NAME; kubectl apply -k .); done
 ```
 
-> **⚠️ Warning:** If you're not sure of the profile name, you can find it in the name space drop-down on the Kubeflow Dashboard.
+Deploy Model Registry:
 
-Check everything is up and running:
+```sh
+kubectl apply -k overlays/db -n $PROFILE_NAME
+kubectl apply -k options/istio -n $PROFILE_NAME
+```
+
+Check that everything is up and running:
 
 ```bash
-kubectl wait --for=condition=available-n ${PROFILE_NAME} deployment/model-registry-deployment --timeout=2m
-kubectl logs -n ${PROFILE_NAME} deployment/model-registry-deployment
+kubectl wait --for=condition=available-n $PROFILE_NAME deployment/model-registry-deployment --timeout=2m
+kubectl logs -n $PROFILE_NAME deployment/model-registry-deployment
 ```
 
 Now, to install the Model Registry UI as a Kubeflow component, you need first to deploy the Model Registry UI:
 
 ```bash
-kubectl apply -k options/ui/overlays/istio -n kubeflow
+kubectl apply -k options/ui/overlays/istio
 ```
 
 And then to make it accessible through Kubeflow Central Dashboard, you need to edit the `centraldashboard-config` ConfigMap to add the Model Registry UI link to the Central Dashboard by running the following command:
@@ -69,25 +77,25 @@ To uninstall the Kubeflow Model Registry run:
 ```bash
 # Uninstall Model Registry Instance
 PROFILE_NAME=<your-profile>
-for DIR in options/istio overlays/db ; do (cd $DIR; kustomize edit set namespace $PROFILE_NAME; kubectl delete -k .); done
+kubectl delete -k overlays/db -n $PROFILE_NAME
+kubectl delete -k options/istio -n $PROFILE_NAME
 
 # Uninstall Model Registry UI
-kubectl delete -k options/ui/overlays/istio -n kubeflow
+kubectl delete -k options/ui/overlays/istio
 ```
 
-
 ## Model Registry as a separate component Installation
 
 The following instructions will summarize how to deploy Model Registry as separate component in the context of a default Kubeflow >=1.9 installation.
 
 ```bash
-kubectl apply -k overlays/db
+kubectl apply -k overlays/db -n kubeflow
 ```
 
 As the default Kubeflow installation provides an Istio mesh, apply the necessary manifests:
 
 ```bash
-kubectl apply -k options/istio
+kubectl apply -k options/istio -n kubeflow
 ```
 
 Check everything is up and running:
@@ -121,8 +129,8 @@ To uninstall the Kubeflow Model Registry run:
 
 ```bash
 # Delete istio options
-kubectl delete -k options/istio
+kubectl delete -k options/istio -n kubeflow
 
 # Delete model registry db and deployment
-kubectl delete -k overlays/db
+kubectl delete -k overlays/db -n kubeflow
 ```
diff --git a/manifests/kustomize/base/model-registry-deployment.yaml b/manifests/kustomize/base/model-registry-deployment.yaml
index 81382e29..4adfb16e 100644
--- a/manifests/kustomize/base/model-registry-deployment.yaml
+++ b/manifests/kustomize/base/model-registry-deployment.yaml
@@ -91,7 +91,7 @@ spec:
           args: ["--grpc_port=9090",
                  "--mysql_config_database=$(MYSQL_DATABASE)",
                  "--mysql_config_host=$(MYSQL_HOST)",
-                 "--mysql_config_port=$(MYSQL_PORT)",
+                 "--mysql_config_port=MYSQL_PORT_PLACEHOLDER",
                  "--mysql_config_user=$(DBCONFIG_USER)",
                  "--mysql_config_password=$(DBCONFIG_PASSWORD)",
                  "--enable_database_upgrade=true"
diff --git a/manifests/kustomize/options/istio/kustomization.yaml b/manifests/kustomize/options/istio/kustomization.yaml
index 91263f9b..029a6937 100644
--- a/manifests/kustomize/options/istio/kustomization.yaml
+++ b/manifests/kustomize/options/istio/kustomization.yaml
@@ -1,6 +1,5 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
-namespace: kubeflow
 
 resources:
 - istio-authorization-policy.yaml
diff --git a/manifests/kustomize/overlays/db/kustomization.yaml b/manifests/kustomize/overlays/db/kustomization.yaml
index cf53e416..e3e2ec86 100644
--- a/manifests/kustomize/overlays/db/kustomization.yaml
+++ b/manifests/kustomize/overlays/db/kustomization.yaml
@@ -1,6 +1,5 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
-namespace: kubeflow
 
 resources:
 - model-registry-db-pvc.yaml
@@ -8,8 +7,6 @@ resources:
 - model-registry-db-service.yaml
 - ../../base
 
-patchesStrategicMerge:
-- patches/model-registry-deployment.yaml
 
 configMapGenerator:
 - envs:
@@ -26,20 +23,47 @@ generatorOptions:
 images:
 - name: mysql
   newName: mysql
-  newTag: 8.0.39
+  newTag: 8.3.0
 
-vars:
-- fieldref:
+patches:
+- path: patches/model-registry-deployment.yaml
+replacements:
+- source:
     fieldPath: metadata.name
-  name: MLMD_DB_HOST
-  objref:
-    apiVersion: v1
     kind: Service
     name: model-registry-db
-- name: MYSQL_PORT
-  objref:
+    version: v1
+  targets:
+  - fieldPaths:
+    - spec.template.spec.containers.1.args.1
+    options:
+      delimiter: =
+      index: 1
+    select:
+      group: apps
+      kind: Deployment
+      name: model-registry-deployment
+      version: v1
+- source:
+    fieldPath: data.MYSQL_PORT
     kind: ConfigMap
     name: model-registry-db-parameters
-    apiVersion: v1
-  fieldref:
-    fieldpath: data.MYSQL_PORT
+    version: v1
+  targets:
+  - fieldPaths:
+    - spec.template.spec.containers.1.args.3
+    options:
+      delimiter: =
+      index: 1
+    select:
+      group: apps
+      kind: Deployment
+      name: model-registry-deployment
+      version: v1
+  - fieldPaths:
+    - spec.template.metadata.annotations.[traffic.sidecar.istio.io/excludeOutboundPorts]
+    select:
+      group: apps
+      kind: Deployment
+      name: model-registry-deployment
+      version: v1
diff --git a/manifests/kustomize/overlays/db/patches/model-registry-deployment.yaml b/manifests/kustomize/overlays/db/patches/model-registry-deployment.yaml
index b6eca64d..0d61bf30 100644
--- a/manifests/kustomize/overlays/db/patches/model-registry-deployment.yaml
+++ b/manifests/kustomize/overlays/db/patches/model-registry-deployment.yaml
@@ -7,7 +7,7 @@ spec:
     metadata:
       annotations:
         # db doesn't use istio
-        traffic.sidecar.istio.io/excludeOutboundPorts: $(MYSQL_PORT)
+        traffic.sidecar.istio.io/excludeOutboundPorts: MYSQL_PORT_PLACEHOLDER
     spec:
       containers:
         - name: rest-container
@@ -35,8 +35,8 @@ spec:
           - configMapRef:
               name: model-registry-configmap
           args: ["--grpc_port=$(MODEL_REGISTRY_GRPC_SERVICE_PORT)",
-                 "--mysql_config_host=$(MLMD_DB_HOST)",
+                 "--mysql_config_host=MLMD_DB_HOST_PLACEHOLDER",
                  "--mysql_config_database=$(MYSQL_DATABASE)",
-                 "--mysql_config_port=$(MYSQL_PORT)",
+                 "--mysql_config_port=MYSQL_PORT_PLACEHOLDER",
                  "--mysql_config_user=$(MYSQL_USER_NAME)",
                  "--mysql_config_password=$(MYSQL_ROOT_PASSWORD)"]
diff --git a/manifests/kustomize/overlays/postgres/kustomization.yaml b/manifests/kustomize/overlays/postgres/kustomization.yaml
index 6a3822d8..0f81c89a 100644
--- a/manifests/kustomize/overlays/postgres/kustomization.yaml
+++ b/manifests/kustomize/overlays/postgres/kustomization.yaml
@@ -1,25 +1,21 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
-namespace: kubeflow
 
-bases:
-- ../../base
 resources:
 - model-registry-db-pvc.yaml
 - model-registry-db-deployment.yaml
 - model-registry-db-service.yaml
+- ../../base
 
-patchesStrategicMerge:
-- patches/model-registry-deployment.yaml
 
 configMapGenerator:
-- name: metadata-registry-db-parameters
-  envs:
+- envs:
   - params.env
+  name: metadata-registry-db-parameters
 secretGenerator:
-- name: metadata-registry-db-secrets
-  envs:
+- envs:
   - secrets.env
+  name: metadata-registry-db-secrets
 generatorOptions:
   disableNameSuffixHash: true
 
@@ -28,18 +24,45 @@ images:
   newName: postgres
   newTag: 14.7-alpine3.17
 
-vars:
-- name: MLMD_DB_HOST
-  objref:
+patches:
+- path: patches/model-registry-deployment.yaml
+replacements:
+- source:
+    fieldPath: metadata.name
     kind: Service
     name: metadata-postgres-db
-    apiVersion: v1
-  fieldref:
-    fieldpath: metadata.name
-- name: POSTGRES_PORT
-  objref:
+    version: v1
+  targets:
+  - fieldPaths:
+    - spec.template.spec.containers.0.args.2
+    options:
+      delimiter: =
+      index: 1
+    select:
+      group: apps
+      kind: Deployment
+      name: model-registry-deployment
+      version: v1
+- source:
+    fieldPath: data.POSTGRES_PORT
     kind: ConfigMap
     name: metadata-registry-db-parameters
-    apiVersion: v1
-  fieldref:
-    fieldpath: data.POSTGRES_PORT
+    version: v1
+  targets:
+  - fieldPaths:
+    - spec.template.metadata.annotations.[traffic.sidecar.istio.io/excludeOutboundPorts]
+    select:
+      group: apps
+      kind: Deployment
+      name: model-registry-deployment
+      version: v1
+  - fieldPaths:
+    - spec.template.spec.containers.0.args.3
+    options:
+      delimiter: =
+      index: 1
+    select:
+      group: apps
+      kind: Deployment
+      name: model-registry-deployment
+      version: v1
diff --git a/manifests/kustomize/overlays/postgres/patches/model-registry-deployment.yaml b/manifests/kustomize/overlays/postgres/patches/model-registry-deployment.yaml
index 9844feaa..1dec4cd7 100644
--- a/manifests/kustomize/overlays/postgres/patches/model-registry-deployment.yaml
+++ b/manifests/kustomize/overlays/postgres/patches/model-registry-deployment.yaml
@@ -7,7 +7,7 @@ spec:
     metadata:
       annotations:
         # db doesn't use istio
-        traffic.sidecar.istio.io/excludeOutboundPorts: $(POSTGRES_PORT)
+        traffic.sidecar.istio.io/excludeOutboundPorts: POSTGRES_PORT_PLACEHOLDER
     spec:
       containers:
         - name: grpc-container
@@ -23,8 +23,8 @@ spec:
               name: model-registry-configmap
           args: ["--grpc_port=$(MODEL_REGISTRY_GRPC_SERVICE_PORT)",
                  "--metadata_source_config_type=postgresql",
-                 "--postgres_config_host=$(MLMD_DB_HOST)",
-                 "--postgres_config_port=$(POSTGRES_PORT)",
+                 "--postgres_config_host=MLMD_DB_HOST_PLACEHOLDER",
+                 "--postgres_config_port=POSTGRES_PORT_PLACEHOLDER",
                  "--postgres_config_dbname=$(POSTGRES_DBNAME)",
                  "--postgres_config_user=$(POSTGRES_USER)",
                  "--postgres_config_password=$(POSTGRES_PASSWORD)",
diff --git a/scripts/deploy_on_kind.sh b/scripts/deploy_on_kind.sh
index cdb5a62c..a8fec3c7 100755
--- a/scripts/deploy_on_kind.sh
+++ b/scripts/deploy_on_kind.sh
@@ -35,14 +35,14 @@ else
     kubectl create namespace "$MR_NAMESPACE"
 fi
 
-kubectl apply -k manifests/kustomize/overlays/db
+kubectl apply -k manifests/kustomize/overlays/db -n "$MR_NAMESPACE"
 kubectl patch deployment -n "$MR_NAMESPACE" model-registry-deployment \
 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "rest-container", "image": "'$IMG'", "imagePullPolicy": "IfNotPresent"}]}}}}'
 
 if ! kubectl wait --for=condition=available -n "$MR_NAMESPACE" deployment/model-registry-db --timeout=5m ; then
     kubectl events -A
-    kubectl describe deployment/model-registry-db -n kubeflow
-    kubectl logs deployment/model-registry-db -n kubeflow
+    kubectl describe deployment/model-registry-db -n "$MR_NAMESPACE"
+    kubectl logs deployment/model-registry-db -n "$MR_NAMESPACE"
     exit 1
 fi
 
diff --git a/scripts/merge_openapi.sh b/scripts/merge_openapi.sh
new file mode 100755
index 00000000..bb9bfbc7
--- /dev/null
+++ b/scripts/merge_openapi.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+set -e
+
+cd "$(pwd)/$(dirname "$0")/.."
+YQ=${YQ:-$(realpath -e "bin/yq")}
+
+usage() {
+    echo "Usage: $0 [--check] <basename.yaml>"
+    echo "  --check: Check for differences in the generated OpenAPI spec."
+    exit 0
+}
+
+CHECK=false
+BASENAME=""
+while [[ $# -gt 0 ]]; do
+    case "$1" in
+        --check)
+            CHECK=true
+            shift
+            ;;
+        -h|--help)
+            usage
+            ;;
+        *)
+            if [[ "${1#-}" != "$1" ]]; then
+                echo "Unknown option: $1"
+                usage
+            fi
+            if [[ "$BASENAME" != "" ]]; then
+                usage
+            fi
+
+            BASENAME=$1
+            shift
+            ;;
+    esac
+done
+
+if [[ "$BASENAME" == "" ]]; then
+    usage
+fi
+
+BASENAME=$(basename $BASENAME)
+SOURCE_FILE="api/openapi/src/$BASENAME"
+if [[ ! -f "$SOURCE_FILE" ]]; then
+    echo "No source file at $SOURCE_FILE"
+    exit 1
+fi
+
+OUT_FILE="api/openapi/$BASENAME"
+if [[ "$CHECK" == "true" ]]; then
+    OUT_FILE=$(mktemp --suffix=.yaml)
+    trap 'rm "$OUT_FILE"' EXIT
+fi
+
+# Merge the src files together.
+$YQ eval-all '. as $item ireduce ({}; . * $item )' $SOURCE_FILE api/openapi/src/lib/*.yaml >"$OUT_FILE"
+
+# Re-order the keys in the generated file.
+$YQ eval -i '
+    {
+        "openapi": .openapi,
+        "info": .info,
+        "servers": .servers,
+        "paths": .paths,
+        "components": .components,
+        "security": .security,
+        "tags": .tags
+    } |
+        sort_keys(.paths) |
+        sort_keys(.components.schemas) |
+        sort_keys(.components.responses)
+' "$OUT_FILE"
+
+if [[ "$CHECK" == "true" ]]; then
+    exec diff -u api/openapi/$BASENAME $OUT_FILE
+fi



Test patch:
diff --git a/clients/python/tests/types/test_context.py b/clients/python/tests/types/test_context.py
new file mode 100644
index 00000000..a583f1a4
--- /dev/null
+++ b/clients/python/tests/types/test_context.py
@@ -0,0 +1,57 @@
+from model_registry.types.contexts import ModelVersion, RegisteredModel
+
+
+def test_model_version_repr():
+    """Test the repr of a ModelVersion, with name to the front, ensuring other fields are also present"""
+    mv = ModelVersion(name="Version 1", id="123", author="test_author", description="test_description")
+    print(mv)
+    assert str(mv).startswith("name='Version 1'")
+    assert "id='123'" in str(mv)
+    assert "author='test_author'" in str(mv)
+    assert "description='test_description'" in str(mv)
+    print(repr(mv))
+    assert repr(mv).startswith("ModelVersion(name='Version 1'")
+    assert "id='123'" in str(mv)
+    assert "author='test_author'" in str(mv)
+    assert "description='test_description'" in str(mv)
+
+    # Test with empty name, not really used in practice but to increase coverage
+    mv = ModelVersion(name="", id="123", author="test_author", description="test_description")
+    print(mv)
+    assert str(mv).startswith("name=''")
+    assert "id='123'" in str(mv)
+    assert "author='test_author'" in str(mv)
+    assert "description='test_description'" in str(mv)
+    print(repr(mv))
+    assert repr(mv).startswith("ModelVersion(name=''")
+    assert "id='123'" in str(mv)
+    assert "author='test_author'" in str(mv)
+    assert "description='test_description'" in str(mv)
+
+
+def test_registered_model_repr():
+    """Test the repr of a RegisteredModel, with name to the front, ensuring other fields are also present"""
+    rm = RegisteredModel(name="Model 1", id="123", owner="test_owner", description="test_description")
+    print(rm)
+    assert str(rm).startswith("name='Model 1'")
+    assert "id='123'" in str(rm)
+    assert "owner='test_owner'" in str(rm)
+    assert "description='test_description'" in str(rm)
+    print(repr(rm))
+    assert repr(rm).startswith("RegisteredModel(name='Model 1'")
+    assert "id='123'" in str(rm)
+    assert "owner='test_owner'" in str(rm)
+    assert "description='test_description'" in str(rm)
+
+    # Test with empty name, not really used in practice but to increase coverage
+    rm = RegisteredModel(name="", id="123", owner="test_owner", description="test_description")
+    print(rm)
+    assert str(rm).startswith("name=''")
+    assert "id='123'" in str(rm)
+    assert "owner='test_owner'" in str(rm)
+    assert "description='test_description'" in str(rm)
+    print(repr(rm))
+    assert repr(rm).startswith("RegisteredModel(name=''")
+    assert "id='123'" in str(rm)
+    assert "owner='test_owner'" in str(rm)
+    assert "description='test_description'" in str(rm)
diff --git a/internal/datastore/embedmd/mysql/migrate_test.go b/internal/datastore/embedmd/mysql/migrate_test.go
new file mode 100644
index 00000000..bdeab6cf
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/migrate_test.go
@@ -0,0 +1,125 @@
+package mysql_test
+
+import (
+	"context"
+	"path/filepath"
+	"testing"
+
+	"github.com/kubeflow/model-registry/internal/datastore/embedmd/mysql"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	"github.com/testcontainers/testcontainers-go"
+	cont_mysql "github.com/testcontainers/testcontainers-go/modules/mysql"
+	"gorm.io/gorm"
+)
+
+// Type represents the Type table structure
+type Type struct {
+	ID          int64  `gorm:"primaryKey"`
+	Name        string `gorm:"column:name"`
+	Version     string `gorm:"column:version"`
+	ExternalID  string `gorm:"column:external_id"`
+	Description string `gorm:"column:description"`
+}
+
+func (Type) TableName() string {
+	return "Type"
+}
+
+// TypeProperty represents the TypeProperty table structure
+type TypeProperty struct {
+	ID          int64  `gorm:"primaryKey"`
+	TypeID      int64  `gorm:"column:type_id"`
+	Name        string `gorm:"column:name"`
+	DataType    string `gorm:"column:data_type"`
+	Description string `gorm:"column:description"`
+}
+
+func (TypeProperty) TableName() string {
+	return "TypeProperty"
+}
+
+func setupTestDB(t *testing.T) (*gorm.DB, func()) {
+	ctx := context.Background()
+
+	mysqlContainer, err := cont_mysql.Run(
+		ctx,
+		"mysql:5.7",
+		cont_mysql.WithUsername("root"),
+		cont_mysql.WithPassword("root"),
+		cont_mysql.WithDatabase("test"),
+		cont_mysql.WithConfigFile(filepath.Join("testdata", "testdb.cnf")),
+	)
+	require.NoError(t, err)
+
+	dbConnector := mysql.NewMySQLDBConnector(mysqlContainer.MustConnectionString(ctx))
+	require.NoError(t, err)
+
+	db, err := dbConnector.Connect()
+	require.NoError(t, err)
+
+	// Return cleanup function
+	cleanup := func() {
+		sqlDB, err := db.DB()
+		require.NoError(t, err)
+		sqlDB.Close() //nolint:errcheck
+		err = testcontainers.TerminateContainer(
+			mysqlContainer,
+		)
+		require.NoError(t, err)
+	}
+
+	return db, cleanup
+}
+
+func TestMigrations(t *testing.T) {
+	db, cleanup := setupTestDB(t)
+	defer cleanup()
+
+	// Create migrator
+	migrator, err := mysql.NewMySQLMigrator(db)
+	require.NoError(t, err)
+
+	// Run migrations
+	err = migrator.Migrate()
+	require.NoError(t, err)
+
+	// Verify MLMDEnv table
+	var schemaVersion int
+	err = db.Raw("SELECT schema_version FROM MLMDEnv LIMIT 1").Scan(&schemaVersion).Error
+	require.NoError(t, err)
+	assert.Equal(t, 10, schemaVersion)
+
+	// Verify Type table has expected entries
+	var count int64
+	err = db.Model(&Type{}).Count(&count).Error
+	require.NoError(t, err)
+	assert.Greater(t, count, int64(0))
+
+	// Verify TypeProperty table has expected entries
+	err = db.Model(&TypeProperty{}).Count(&count).Error
+	require.NoError(t, err)
+	assert.Greater(t, count, int64(0))
+}
+
+func TestDownMigrations(t *testing.T) {
+	db, cleanup := setupTestDB(t)
+	defer cleanup()
+
+	migrator, err := mysql.NewMySQLMigrator(db)
+	require.NoError(t, err)
+
+	// Run migrations
+	err = migrator.Migrate()
+	require.NoError(t, err)
+
+	// Down migrations
+	err = migrator.Down(nil)
+	require.NoError(t, err)
+
+	// Verify tables don't exist (except schema_migrations)
+	var count int64
+	err = db.Raw("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name != 'schema_migrations'").Scan(&count).Error
+	require.NoError(t, err)
+	assert.Equal(t, int64(0), count)
+}
diff --git a/internal/datastore/embedmd/mysql/testdata/testdb.cnf b/internal/datastore/embedmd/mysql/testdata/testdb.cnf
new file mode 100644
index 00000000..873958cd
--- /dev/null
+++ b/internal/datastore/embedmd/mysql/testdata/testdb.cnf
@@ -0,0 +1,5 @@
+[mysqld]
+character-set-server = utf8mb4
+collation-server = utf8mb4_general_ci
+
+!includedir /etc/mysql/conf.d/