diff --git a/.fossa.yml b/.fossa.yml
index 7345631966a675a72b68ca6af74becbcd6ba05f4..773df900e81486eb61492cb927bceae773caafb3 100644
--- a/.fossa.yml
+++ b/.fossa.yml
@@ -16,6 +16,10 @@ analyze:
       type: mvn
       target: schema-core/pom.xml
       path: .
+    - name: schema-core-plus
+      type: mvn
+      target: schema-core-plus/pom.xml
+      path: .
     - name: os-schema-aws
       type: mvn
       target: provider/schema-aws/pom.xml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 937d922ca4c3e101cdd9f22b6750f0c8ce84bef9..a4ded63e7ee2b1de1040749ba448ff17c3581afb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -86,6 +86,7 @@ include:
   - local: "/devops/azure/override-stages.yml"
   - local: "/devops/aws/bootstrap.yaml"
   - local: "/devops/ibm/bootstrap.yaml"
+  - local: "/devops/core-plus/pipeline/override-stages.yml"
 
 .maven:
   image: maven:3.9.3-eclipse-temurin-17
@@ -185,6 +186,32 @@ include:
     - echo "#!/bin/sh" > $MAVEN_FOREACH
     - echo 'xargs -0rI {} $MAVEN_BUILD {} "$@" < $ALL_MAVEN_BUILD_DIRS_Z' >> $MAVEN_FOREACH
 
+download_plugins:
+  image: maven:3.8.3-openjdk-17-slim
+  stage: build
+  variables:
+    OSM_PACKAGE_REGISTRY_URL: "https://community.opengroup.org/api/v4/projects/1448/packages/maven"
+    OSM_VERSION: "0.25.0-rc2"
+    OBM_PACKAGE_REGISTRY_URL: "https://community.opengroup.org/api/v4/projects/1441/packages/maven"
+    OBM_VERSION: "0.25.0-rc1"
+    OQM_PACKAGE_REGISRTY_URL: "https://community.opengroup.org/api/v4/projects/1450/packages/maven"
+    OQM_VERSION: "0.25.0-rc1"
+
+  artifacts:
+    paths:
+      - ./tmp/*.jar
+    when: always
+    expire_in: 1 days
+
+  script:
+    - mvn dependency:copy -DrepoUrl=$OSM_PACKAGE_REGISTRY_URL -Dartifact="org.opengroup.osdu:os-osm-postgres:$OSM_VERSION:jar:plugin" -Dtransitive=false -DoutputDirectory="./tmp"
+    - mvn dependency:copy -DrepoUrl=$OBM_PACKAGE_REGISTRY_URL -Dartifact="org.opengroup.osdu:os-obm-minio:$OBM_VERSION:jar:plugin" -Dtransitive=false -DoutputDirectory="./tmp"
+    - mvn dependency:copy -DrepoUrl=$OQM_PACKAGE_REGISRTY_URL -Dartifact="org.opengroup.osdu:os-oqm-rabbitmq:$OQM_VERSION:jar:plugin" -Dtransitive=false -DoutputDirectory="./tmp"
+
+  only:
+    variables:
+      - $PROTECTED == '1'
+
 gemnasium-maven-dependency_scanning:
   variables:
     DS_JAVA_VERSION: 17
diff --git a/NOTICE b/NOTICE
index 37e94ef44b0e4d4470a0e2c2f57b8278b1cd93b6..17bb7eb844b7a5fcef90f78592f9a7a1f4e88dd8 100644
--- a/NOTICE
+++ b/NOTICE
@@ -579,12 +579,14 @@ The following software have components provided under the terms of this license:
 - io.grpc:grpc-core (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-googleapis (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-grpclb (from https://github.com/grpc/grpc-java)
+- io.grpc:grpc-inprocess (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-netty-shaded (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-protobuf (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-protobuf-lite (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-rls (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-services (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-stub (from https://github.com/grpc/grpc-java)
+- io.grpc:grpc-util (from https://github.com/grpc/grpc-java)
 - io.grpc:grpc-xds (from https://github.com/grpc/grpc-java)
 - ion-java (from https://github.com/amzn/ion-java/, https://github.com/amznlabs/ion-java/)
 - jackson-databind (from http://github.com/FasterXML/jackson, http://wiki.fasterxml.com/JacksonHome, https://github.com/FasterXML/jackson)
@@ -613,6 +615,7 @@ The following software have components provided under the terms of this license:
 - requests (from http://python-requests.org, https://requests.readthedocs.io)
 - resilience4j (from https://github.com/resilience4j/resilience4j, https://resilience4j.readme.io, ttps://resilience4j.readme.io)
 - snappy-java (from https://github.com/xerial/snappy-java)
+- spring-boot-loader (from https://spring.io/projects/spring-boot)
 - spring-security-oauth2-core (from http://spring.io/spring-security, https://spring.io/projects/spring-security, https://spring.io/spring-security)
 - spring-security-oauth2-jose (from http://spring.io/spring-security, https://spring.io/projects/spring-security, https://spring.io/spring-security)
 - springdoc-openapi-common (from <https://repo1.maven.org/maven2/org/springdoc/springdoc-openapi-common>, https://repo1.maven.org/maven2/org/springdoc/springdoc-openapi-common)
@@ -993,13 +996,6 @@ The following software have components provided under the terms of this license:
 
 - RabbitMQ Java Client (from http://www.rabbitmq.com, https://www.rabbitmq.com)
 
-========================================================================
-RSA-MD
-========================================================================
-The following software have components provided under the terms of this license:
-
-- AWS Java SDK for Amazon SQS (from https://aws.amazon.com/sdkforjava)
-
 ========================================================================
 WTFPL
 ========================================================================
diff --git a/devops/core-plus/pipeline/override-stages.yml b/devops/core-plus/pipeline/override-stages.yml
new file mode 100644
index 0000000000000000000000000000000000000000..380b35914c2ee39ef2f7fd3704f730106d3cac98
--- /dev/null
+++ b/devops/core-plus/pipeline/override-stages.yml
@@ -0,0 +1,101 @@
+gc-containerize-gitlab:core-plus:
+  stage: containerize
+  needs:
+    - "compile-and-unit-test"
+    - "download_plugins"
+  tags: ["osdu-small"]
+  image: docker:19.03
+  cache: {}
+  variables:
+    BUILD_ARGS: "--build-arg PORT=$GC_PORT"
+    BUILD_PATH: "schema-core-plus/cloudbuild/Dockerfile"
+    IMAGE_NAME: "schema-core-plus"
+  script:
+    - !reference [.gc_set_image_name, script]
+    - docker build $EXTRA_TAG -f $BUILD_PATH $BUILD_ARGS .
+    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+    - docker push $CI_REGISTRY_IMAGE/$IMAGE_NAME
+  rules:
+    - if: "$CI_COMMIT_BRANCH =~ /^release/"
+      when: never
+    - if: "$CI_COMMIT_TAG"
+      when: never
+    - if: "$PROTECTED == '1'"
+      when: on_success
+
+gc-helm-charts-gitlab:core-plus:
+  stage: containerize
+  tags: ["osdu-small"]
+  needs: ["gc-containerize-gitlab:core-plus"]
+  image:
+    name: alpine/helm:3.11.2
+    entrypoint: [""]
+  variables:
+    IMAGE_NAME: "schema-core-plus"
+  before_script:
+    - helm registry login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+    - !reference [.gc_set_image_name, script]
+    - !reference [.gc_substitute_image_in_helm, script]
+  script:
+    - !reference [.gc_define_app_version, script]
+    - helm package $GC_HELM_DEPLOYMENT_DIR -u --version $GC_HELM_PACKAGE_VERSION-$HELM_TAG --app-version $APP_VERSION
+    - helm push $GC_HELM_PACKAGE_NAME-$GC_HELM_PACKAGE_VERSION-$HELM_TAG.tgz oci://$CI_REGISTRY_IMAGE/core-plus-helm
+  rules:
+    - if: "$CI_COMMIT_BRANCH =~ /^release/"
+      when: never
+    - if: "$CI_COMMIT_TAG"
+      when: never
+    - if: "$PROTECTED == '1'"
+      when: on_success
+
+gc-baremetal-deploy:
+  environment:
+    name: GC_Baremetal
+  extends: .gc-baremetal-variables
+  id_tokens:
+    GITLAB_OIDC_TOKEN:
+      aud: https://iam.googleapis.com/projects/${GC_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GC_POOL_ID}/providers/${GC_PROVIDER_ID}
+  tags: ["osdu-small"]
+  image: gcr.io/google.com/cloudsdktool/cloud-sdk:alpine
+  stage: deploy
+  needs:
+    - "gc-containerize-gitlab:core-plus"
+    - "gc-helm-charts-gitlab:core-plus"
+  retry: 1
+  variables:
+    IMAGE_NAME: "schema-core-plus"
+    GC_SA_EMAIL: $GC_SA_GKE_EMAIL
+  script:
+    - !reference [.gc_obtain_credentials, script]
+    - !reference [.gc_set_image_name, script]
+    - !reference [.gc_common_config, script]
+    - >
+      helm upgrade $GC_SERVICE-deploy oci://$CI_REGISTRY_IMAGE/core-plus-helm/$GC_HELM_PACKAGE_NAME
+      --version $GC_HELM_PACKAGE_VERSION-$HELM_TAG
+      --install
+      --create-namespace
+      --namespace=$GC_HELM_NAMESPACE
+      --wait
+      --history-max=3
+      --set global.onPremEnabled=true
+      --set global.domain=$GC_DOMAIN
+      --set data.serviceAccountName=$GC_SERVICE
+      --set data.bootstrapServiceAccountName=$GC_BOOTSTRAP_SA
+      --set data.logLevel=INFO
+      --set data.springProfilesActive=$GC_SPRING_PROFILES_ACTIVE
+      --set data.dataPartitionId=$GC_TENANT
+    - !reference [.gc_verify_deploy, script]
+    - !reference [.gc_verify_bootstrap, script]
+  rules:
+    - if: "$CI_COMMIT_BRANCH =~ /^release/"
+      when: never
+    - if: "$CI_COMMIT_TAG"
+      when: never
+    - if: "$PROTECTED == '1'"
+      when: on_success
+
+gc-baremetal-test:
+  variables:
+    GC_TEST_SUBDIR: testing/schema-test-core
+  script:
+    - $MAVEN_BUILD . test-results.log verify -q -f $GC_TEST_SUBDIR/pom.xml
diff --git a/devops/gc/deploy/templates/configmap.yaml b/devops/gc/deploy/templates/configmap.yaml
index 5d6cc66ecb631d12d2eb0221c2ca3ec38564a7cc..ec5b5a7acde940d0269ec5b128785708173cf62d 100644
--- a/devops/gc/deploy/templates/configmap.yaml
+++ b/devops/gc/deploy/templates/configmap.yaml
@@ -8,8 +8,8 @@ metadata:
 data:
   LOG_LEVEL: {{ .Values.data.logLevel | quote }}
   ENTITLEMENTS_HOST: {{ .Values.data.entitlementsHost | quote }}
-  GCP_SCHEMA_CHANGED_TOPIC_NAME: {{ .Values.data.schemaTopicName | quote }}
-  GCP_SCHEMA_CHANGED_MESSAGING_ENABLED: {{ .Values.data.schemaChangedMessagingEnabled | quote }}
+  SCHEMA_CHANGED_TOPIC_NAME: {{ .Values.data.schemaTopicName | quote }}
+  SCHEMA_CHANGED_MESSAGING_ENABLED: {{ .Values.data.schemaChangedMessagingEnabled | quote }}
   PARTITION_HOST: {{ .Values.data.partitionHost | quote }}
   SHARED_TENANT_NAME: {{ .Values.data.dataPartitionId | quote }}
   SPRING_PROFILES_ACTIVE: {{ .Values.data.springProfilesActive | quote }}
diff --git a/devops/gc/pipeline/override-stages.yml b/devops/gc/pipeline/override-stages.yml
index e7441419c28abf2f4d72f7c03d7cb183233ff7dd..614d3571f9eee3822d42bfc83e6f6527418973be 100644
--- a/devops/gc/pipeline/override-stages.yml
+++ b/devops/gc/pipeline/override-stages.yml
@@ -19,11 +19,5 @@ gc-dev2-test:
   script:
     - $MAVEN_BUILD . test-results.log verify -q -f $GC_TEST_SUBDIR/pom.xml
 
-gc-baremetal-test:
-  variables:
-    GC_TEST_SUBDIR: testing/schema-test-core
-  script:
-    - $MAVEN_BUILD . test-results.log verify -q -f $GC_TEST_SUBDIR/pom.xml
-
 gc-containerize-bootstrap-gitlab:
   tags: ["osdu-medium"]
diff --git a/pom.xml b/pom.xml
index 023bb2cba12d2eb44a6117673606082a5cb11089..afebf474385387fedb0e65a0b95baffa82e5625a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,7 @@
 
 	<modules>
 		<module>schema-core</module>
+		<module>schema-core-plus</module>
 		<module>provider/schema-aws</module>
 		<module>provider/schema-gc</module>
 		<module>provider/schema-ibm</module>
diff --git a/provider/schema-gc/docs/anthos/README.md b/provider/schema-gc/docs/anthos/README.md
index 5f097ae84b3ff040e260bb1411a94efa874af76a..699c8cb1ea2e5daae3de00fa552d13aa3f36d517 100644
--- a/provider/schema-gc/docs/anthos/README.md
+++ b/provider/schema-gc/docs/anthos/README.md
@@ -25,8 +25,8 @@ Defined in default application property file but possible to override:
 | `AUTHORIZE_API`                                  | ex `https://entitlements.com/entitlements/v1` | Entitlements API endpoint                                               | no         | output of infrastructure deployment                          |
 | `PARTITION_API`                                  | ex `http://localhost:8081/api/partition/v1`   | Partition service endpoint                                              | no         | -                                                            |
 | `GOOGLE_APPLICATION_CREDENTIALS`                 | ex `/path/to/directory/service-key.json`      | Service account credentials, you only need this if running locally      | yes        | <https://console.cloud.google.com/iam-admin/serviceaccounts> |
-| `GCP_SCHEMA_CHANGED_MESSAGING_ENABLED`           | `true` OR `false`                             | Allows to configure message publishing about schemas changes to Pub/Sub | no         | -                                                            |
-| `GCP_SCHEMA_CHANGED_TOPIC_NAME`                  | `schema-changed`                              | Topic for schema changes events                                         | no         | -                                                            |
+| `SCHEMA_CHANGED_MESSAGING_ENABLED`               | `true` OR `false`                             | Allows to configure message publishing about schemas changes to Pub/Sub | no         | -                                                            |
+| `SCHEMA_CHANGED_TOPIC_NAME`                      | `schema-changed`                              | Topic for schema changes events                                         | no         | -                                                            |
 | `PARTITION_PROPERTIES_SCHEMA_BUCKET_NAME`        | ex `schema.bucket.name`                       | name of partition property for schema bucket name value                 | yes        | -                                                            |
 | `PARTITION_PROPERTIES_SYSTEM_SCHEMA_BUCKET_NAME` | ex `system.schema.bucket.name`                | name of partition property for system schema bucket name value          | yes        | -                                                            |
 
diff --git a/provider/schema-gc/docs/gc/README.md b/provider/schema-gc/docs/gc/README.md
index 37405b879da06f8701a35f68b09a01627e5febcf..a28adbb0a6fec789326c9a2f3e36ee1cf7f7b14a 100644
--- a/provider/schema-gc/docs/gc/README.md
+++ b/provider/schema-gc/docs/gc/README.md
@@ -21,8 +21,8 @@ Defined in default application property file but possible to override:
 | `AUTHORIZE_API`                                  | ex `https://entitlements.com/entitlements/v1` | Entitlements API endpoint                                               | no         | output of infrastructure deployment                          |
 | `PARTITION_API`                                  | ex `http://localhost:8081/api/partition/v1`   | Partition service endpoint                                              | no         | -                                                            |
 | `GOOGLE_APPLICATION_CREDENTIALS`                 | ex `/path/to/directory/service-key.json`      | Service account credentials, you only need this if running locally      | yes        | <https://console.cloud.google.com/iam-admin/serviceaccounts> |
-| `GCP_SCHEMA_CHANGED_MESSAGING_ENABLED`           | `true` OR `false`                             | Allows to configure message publishing about schemas changes to Pub/Sub | no         | -                                                            |
-| `GCP_SCHEMA_CHANGED_TOPIC_NAME`                  | `schema-changed`                              | Topic for schema changes events                                         | no         | -                                                            |
+| `SCHEMA_CHANGED_MESSAGING_ENABLED`               | `true` OR `false`                             | Allows to configure message publishing about schemas changes to Pub/Sub | no         | -                                                            |
+| `SCHEMA_CHANGED_TOPIC_NAME`                      | `schema-changed`                              | Topic for schema changes events                                         | no         | -                                                            |
 | `PARTITION_PROPERTIES_SCHEMA_BUCKET_NAME`        | ex `schema.bucket.name`                       | name of partition property for schema bucket name value                 | yes        | -                                                            |
 | `PARTITION_PROPERTIES_SYSTEM_SCHEMA_BUCKET_NAME` | ex `system.schema.bucket.name`                | name of partition property for system schema bucket name value          | yes        | -                                                            |
 
diff --git a/provider/schema-gc/pom.xml b/provider/schema-gc/pom.xml
index f8b9659ff469c171200bcb98bf271e82111e4bbe..579feeb5b01bd7bf4aaf783da62b4fea4bb9e007 100644
--- a/provider/schema-gc/pom.xml
+++ b/provider/schema-gc/pom.xml
@@ -7,11 +7,6 @@
 		<relativePath>../../pom.xml</relativePath>
 	</parent>
 
-	<properties>
-		<!-- <jackson-databind.version>2.15.0</jackson-databind.version>
-		<jackson.version>2.15.0</jackson.version> -->
-	</properties>
-
 	<artifactId>os-schema-gc</artifactId>
 	<description>Google cloud related implementation staff.</description>
 	<packaging>jar</packaging>
@@ -71,21 +66,6 @@
 				</exclusion>
 			</exclusions>
 		</dependency>
-		<!--<dependency>
-			<groupId>com.fasterxml.jackson.core</groupId>
-			<artifactId>jackson-databind</artifactId>
-			<version>${jackson-databind.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>com.fasterxml.jackson.core</groupId>
-			<artifactId>jackson-core</artifactId>
-			<version>${jackson.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>com.fasterxml.jackson.core</groupId>
-			<artifactId>jackson-annotations</artifactId>
-			<version>${jackson.version}</version>
-		</dependency>-->
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-webmvc</artifactId>
diff --git a/provider/schema-gc/src/main/java/org/opengroup/osdu/schema/configuration/EventMessagingPropertiesConfig.java b/provider/schema-gc/src/main/java/org/opengroup/osdu/schema/configuration/EventMessagingPropertiesConfig.java
index b787504eefae6d722007fa2bc690d60c70ed099d..94834a57afc23efb141d26017d63dd6d9f5e71bd 100644
--- a/provider/schema-gc/src/main/java/org/opengroup/osdu/schema/configuration/EventMessagingPropertiesConfig.java
+++ b/provider/schema-gc/src/main/java/org/opengroup/osdu/schema/configuration/EventMessagingPropertiesConfig.java
@@ -22,7 +22,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.boot.context.properties.ConstructorBinding;
 
-@ConfigurationProperties(prefix = "gcp.schema-changed")
+@ConfigurationProperties(prefix = "schema-changed")
 @Getter
 @ConstructorBinding
 public class EventMessagingPropertiesConfig {
diff --git a/provider/schema-gc/src/main/resources/application.properties b/provider/schema-gc/src/main/resources/application.properties
index 719237cb52f64bd9acfd1574723254cd52dc735b..1f53472105b5653859681a292970fbbbce2d11fa 100644
--- a/provider/schema-gc/src/main/resources/application.properties
+++ b/provider/schema-gc/src/main/resources/application.properties
@@ -24,12 +24,10 @@ partition.properties.system-schema-bucket-name=system.schema.bucket.name
 ## Use this property to name your shared tenant name
 shared-tenant-name=${SHARED_TENANT_NAME:osdu}
 
-gcp.schema-changed.messagingEnabled=false
-
 ## Status messaging switch
-gcp.schema-changed.messaging-enabled=false
+schema-changed.messaging-enabled=${SCHEMA_CHANGED_MESSAGING_ENABLED:true}
 ## Status messaging target topic
-gcp.schema-changed.topic-name=topicName
+schema-changed.topic-name=${SCHEMA_CHANGED_TOPIC_NAME:schema-changed}
 
 ## not used variable must be set with a placeholder to avoid application run failure
 AUTHORIZE_API_KEY=placeholder
diff --git a/schema-core-plus/README.md b/schema-core-plus/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ac08a0bde768711a4c142e6d821ae2d975651022
--- /dev/null
+++ b/schema-core-plus/README.md
@@ -0,0 +1,132 @@
+# Schema Service
+
+schema-core-plus is a Maven multi-module project service.
+
+## Getting Started
+
+These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
+
+### Prerequisites (Infra and access required)
+
+Pre-requisites
+
+* GCloud SDK with java (latest version)
+* JDK 17
+* Lombok 1.18.26 or later
+* Maven
+
+### Installation
+
+### Service Configuration
+
+#### Baremetal
+
+[Baremetal service configuration](docs/baremetal/README.md)
+
+
+### Run Locally
+
+Check that maven is installed:
+
+```bash
+$ mvn --version
+Apache Maven 3.8.7
+Maven home: /usr/share/maven
+Java 17.0.7
+...
+```
+
+You may need to configure access to the remote maven repository that holds the OSDU dependencies. This file should live within `~/.mvn/community-maven.settings.xml`:
+
+```bash
+$ cat ~/.m2/settings.xml
+<?xml version="1.0" encoding="UTF-8"?>
+<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+    <servers>
+        <server>
+            <id>community-maven-via-private-token</id>
+            <!-- Treat this auth token like a password. Do not share it with anyone, including Microsoft support. -->
+            <!-- The generated token expires on or before 11/14/2019 -->
+             <configuration>
+              <httpHeaders>
+                  <property>
+                      <name>Private-Token</name>
+                      <value>${env.COMMUNITY_MAVEN_TOKEN}</value>
+                  </property>
+              </httpHeaders>
+             </configuration>
+        </server>
+    </servers>
+</settings>
+```
+
+Once the above Prerequisite are done, we can follow the below steps to run the service locally,
+
+1. Navigate to the root of the schema project, os-schema. For building the project using command line, run below command :
+
+    ```bash
+    mvn clean install
+    ```
+
+    This will build the core project as well as all the underlying projects. If we want  to build projects for specific cloud vendor, we can use mvn --projects command. For example, if we want to build only for Google Cloud, we can use below command :
+
+    ```bash
+    mvn --projects schema-core,schema-core-plus clean install
+    ```
+
+2. Run schema service in command line.  
+
+
+Download pluggable OSDU Drivers:
+```bash
+    - mvn dependency:copy -DrepoUrl=$OSM_PACKAGE_REGISTRY_URL -Dartifact="org.opengroup.osdu:os-osm-postgres:$OSM_VERSION:jar:plugin" -Dtransitive=false -DoutputDirectory="./tmp"
+    - mvn dependency:copy -DrepoUrl=$OBM_PACKAGE_REGISTRY_URL -Dartifact="org.opengroup.osdu:os-obm-minio:$OBM_VERSION:jar:plugin" -Dtransitive=false -DoutputDirectory="./tmp"
+    - mvn dependency:copy -DrepoUrl=$OQM_PACKAGE_REGISRTY_URL -Dartifact="org.opengroup.osdu:os-oqm-rabbitmq:$OQM_VERSION:jar:plugin" -Dtransitive=false -DoutputDirectory="./tmp"
+```
+Select schema-core-plus to run :
+```bash
+    java --add-opens java.base/java.lang=ALL-UNNAMED \
+         --add-opens java.base/java.lang.reflect=ALL-UNNAMED \
+         -Djava.security.egd=file:/dev/./urandom \
+         -Dserver.port=${PORT} \
+         -Dlog4j.formatMsgNoLookups=true \
+         -Dloader.path=plugins/ \
+         -Dloader.debug=true \
+         -Dloader.main=org.opengroup.osdu.schema.CorePlusSchemaApplication \
+         -jar schema-core-plus-0.25.0-SNAPSHOT-spring-boot.jar 
+```
+   
+3. The port and path for the service endpoint can be configured in ```application.properties``` in the provider folder as following. If not specified, then  the web container (ex. Tomcat) default is used:
+
+    ```bash
+    server.servlet.contextPath=/api/schema-service/v1/
+    server.port=8080
+   ```
+   
+You can access the service APIs by following the service contract in [schema.yaml](docs/api/schema.yaml)
+
+## Testing
+
+#### Baremetal
+
+[Baremetal Testing](docs/baremetal/README.md)
+
+## License
+
+Copyright © Google LLC
+
+Copyright © EPAM Systems
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/schema-core-plus/cloudbuild/Dockerfile b/schema-core-plus/cloudbuild/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..125dd3864877203efc4da4f7d71cb88bbfdabd56
--- /dev/null
+++ b/schema-core-plus/cloudbuild/Dockerfile
@@ -0,0 +1,27 @@
+FROM azul/zulu-openjdk:17
+WORKDIR /app
+ARG PROVIDER_NAME
+ENV PROVIDER_NAME core-plus
+
+# Copy plugins
+COPY tmp/os-oqm-rabbitmq-*.jar plugins/oqm-rabbitmq.jar
+COPY tmp/os-obm-minio-*.jar plugins/osm-minio.jar
+COPY tmp/os-osm-postgres-*.jar plugins/osm-postgres.jar
+
+# Copy the jar to the production image from the builder stage.
+COPY schema-${PROVIDER_NAME}/target/schema-${PROVIDER_NAME}-*-spring-boot.jar schema.jar
+# Add a non-root user
+RUN groupadd -g 10001 -r nonroot \
+  && useradd -g 10001 -r -u 10001 nonroot
+# Run as non-root user
+USER 10001:10001
+# Run the web service on container startup.
+CMD java --add-opens java.base/java.lang=ALL-UNNAMED \
+         --add-opens java.base/java.lang.reflect=ALL-UNNAMED \
+         -Djava.security.egd=file:/dev/./urandom \
+         -Dserver.port=${PORT} \
+         -Dlog4j.formatMsgNoLookups=true \
+         -Dloader.path=plugins/ \
+         -Dloader.debug=true \
+         -Dloader.main=org.opengroup.osdu.schema.CorePlusSchemaApplication \
+         -jar /app/schema.jar
diff --git a/schema-core-plus/docs/baremetal/README.md b/schema-core-plus/docs/baremetal/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3da32535cdf89e144c860d89172d7dbeccdd7f60
--- /dev/null
+++ b/schema-core-plus/docs/baremetal/README.md
@@ -0,0 +1,501 @@
+## Service Configuration for Baremetal
+
+## Environment variables
+
+Define the following environment variables.
+
+Must have:
+
+| name                                      | value         | description                                                                                                                                                                                                                                                                                                | sensitive? | source |
+|-------------------------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|--------|
+| `SPRING_PROFILES_ACTIVE`                  | ex `anthos`   | Spring profile that activate default configuration for Google Cloud environment                                                                                                                                                                                                                            | false      | -      |
+| `SHARED_TENANT_NAME`                      | ex `anthos`   | Shared account id                                                                                                                                                                                                                                                                                          | no         | -      |
+| `<POSTGRES_PASSWORD_ENV_VARIABLE_NAME>`   | ex `password` | Potgres user, name of that variable not defined at the service level, the name will be received through partition service. Each tenant can have it's own ENV name value, and it must be present in ENV of Indexer service, see [Partition properties set](#properties-set-in-partition-service)            | yes        | -      |
+| `<MINIO_SECRETKEY_ENV_VARIABLE_NAME>`     | ex `password` | Minio password, name of that variable not defined at the service level, the name will be received through partition service. Each tenant can have it's own ENV name value, and it must be present in ENV of Indexer service, see [Partition properties set](#properties-set-in-partition-service)          | yes        | -      |
+| `<AMQP_PASSWORD_ENV_VARIABLE_NAME>`       | ex `password` | RabbitMQ password, name of that variable not defined at the service level, the name will be received through partition service. Each tenant can have it's own ENV name value, and it must be present in ENV of Indexer service, see [Partition properties set](#properties-set-in-partition-service)       | yes        | -      |
+| `<AMQP_ADMIN_PASSWORD_ENV_VARIABLE_NAME>` | ex `password` | RabbitMQ Admin password, name of that variable not defined at the service level, the name will be received through partition service. Each tenant can have it's own ENV name value, and it must be present in ENV of Indexer service, see [Partition properties set](#properties-set-in-partition-service) | yes        | -      |
+
+Defined in default application property file but possible to override:
+
+| name                                             | value                                         | description                                                             | sensitive? | source                                                       |
+|--------------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------------|------------|--------------------------------------------------------------|
+| `LOG_PREFIX`                                     | `schema`                                      | Logging prefix                                                          | no         | -                                                            |
+| `LOG_LEVEL`                                      | `DEBUG`                                       | Logging level                                                           | no         | -                                                            |
+| `SERVER_SERVLET_CONTEXPATH`                      | `/api/schema-service/v1`                      | Servlet context path                                                    | no         | -                                                            |
+| `AUTHORIZE_API`                                  | ex `https://entitlements.com/entitlements/v1` | Entitlements API endpoint                                               | no         | output of infrastructure deployment                          |
+| `PARTITION_API`                                  | ex `http://localhost:8081/api/partition/v1`   | Partition service endpoint                                              | no         | -                                                            |
+| `GOOGLE_APPLICATION_CREDENTIALS`                 | ex `/path/to/directory/service-key.json`      | Service account credentials, you only need this if running locally      | yes        | <https://console.cloud.google.com/iam-admin/serviceaccounts> |
+| `SCHEMA_CHANGED_MESSAGING_ENABLED`               | `true` OR `false`                             | Allows to configure message publishing about schemas changes to Pub/Sub | no         | -                                                            |
+| `SCHEMA_CHANGED_TOPIC_NAME`                      | `schema-changed`                              | Topic for schema changes events                                         | no         | -                                                            |
+| `PARTITION_PROPERTIES_SCHEMA_BUCKET_NAME`        | ex `schema.bucket.name`                       | name of partition property for schema bucket name value                 | yes        | -                                                            |
+| `PARTITION_PROPERTIES_SYSTEM_SCHEMA_BUCKET_NAME` | ex `system.schema.bucket.name`                | name of partition property for system schema bucket name value          | yes        | -                                                            |
+
+These variables define service behavior, and are used to switch between `reference` or `Google Cloud` environments, their overriding
+and usage in mixed mode was not tested. Usage of spring profiles is preferred.
+
+| name                     | value                     | description                                                                                                               | sensitive? | source |
+|--------------------------|---------------------------|---------------------------------------------------------------------------------------------------------------------------|------------|--------|
+| `PARTITION_AUTH_ENABLED` | ex `true` or `false`      | Disable or enable auth token provisioning for requests to Partition service                                               | no         | -      |
+
+## Partition level config
+
+### Non-sensitive partition properties
+| name                                        | value                          | description                          | sensitive? | source                                           |
+|---------------------------------------------|--------------------------------|--------------------------------------|------------|--------------------------------------------------|
+| `<SCHEMA_BUCKET_NAME_PROPERTY_NAME>`        | ex `schema.bucket.name`        | schema address in OBM storage        | no         | `PARTITION_PROPERTIES_SCHEMA_BUCKET_NAME`        |
+| `<SYSTEM_SCHEMA_BUCKET_NAME_PROPERTY_NAME>` | ex `system.schema.bucket.name` | system schema address in OBM storage | no         | `PARTITION_PROPERTIES_SYSTEM_SCHEMA_BUCKET_NAME` |
+
+## Testing
+
+### Running E2E Tests
+
+This section describes how to run cloud OSDU E2E tests (testing/schema-test-core).
+
+You will need to have the following environment variables defined.
+
+| name                                 | value                                   | description                               | sensitive?                              | source |
+|--------------------------------------|-----------------------------------------|-------------------------------------------|-----------------------------------------|--------|
+| `VENDOR`                             | `anthos`                                | Use value 'gcp' to run Google Cloud tests | no                                      | -      |
+| `HOST`                               | ex`http://localhost:8080`               | Schema service host                       | no                                      | -      |
+| `PRIVATE_TENANT2`                    | ex`opendes`                             | OSDU tenant used for testing              | no                                      | -      |
+| `PRIVATE_TENANT1`                    | ex`osdu`                                | OSDU tenant used for testing              | no                                      | -      |
+| `SHARED_TENANT`                      | ex`common`                              | OSDU tenant used for testing              | no                                      | -      |
+| `TEST_OPENID_PROVIDER_CLIENT_ID`     | `********`                              | Client Id for `$INTEGRATION_TESTER`       | yes                                     | --     |
+| `TEST_OPENID_PROVIDER_CLIENT_SECRET` | `********`                              |                                           | Client secret for `$INTEGRATION_TESTER` | --     |
+| `TEST_OPENID_PROVIDER_URL`           | `https://keycloak.com/auth/realms/osdu` | OpenID provider url                       | yes                                     | --     |
+
+**Entitlements configuration for integration accounts**
+
+| INTEGRATION_TESTER                                                                                                                                                                         |
+|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| users<br/>service.schema-service.system-admin<br/>service.entitlements.user<br/>service.schema-service.viewers<br/>service.schema-service.editors<br/>data.integration.test<br/>data.test1 |
+
+Execute following command to build code and run all the integration tests:
+
+ ```bash
+ # Note: this assumes that the environment variables for integration tests as outlined
+ #       above are already exported in your environment.
+ # build + install integration test core
+ $ (cd testing/schema-test-core/ && mvn clean test)
+ ```
+
+### Properties set in Partition service
+
+Note that properties can be set in Partition as `sensitive` in that case in property `value` should be present not value itself, but ENV variable name.
+This variable should be present in environment of service that need that variable.
+
+Example:
+
+```
+    "elasticsearch.port": {
+      "sensitive": false, <- value not sensitive 
+      "value": "9243"  <- will be used as is.
+    },
+      "elasticsearch.password": {
+      "sensitive": true, <- value is sensitive 
+      "value": "ELASTIC_SEARCH_PASSWORD_OSDU" <- service consumer should have env variable ELASTIC_SEARCH_PASSWORD_OSDU with elastic search password
+    }
+```
+
+## Postgres configuration
+
+### Properties set in Partition service
+
+**prefix:** `osm.postgres`
+
+It can be overridden by:
+
+- through the Spring Boot property `osm.postgres.partition-properties-prefix`
+- environment variable `OSM_POSTGRES_PARTITION_PROPERTIES_PREFIX`
+
+**Propertyset:**
+
+| Property                         | Description |
+|----------------------------------|-------------|
+| osm.postgres.datasource.url      | server URL  |
+| osm.postgres.datasource.username | username    |
+| osm.postgres.datasource.password | password    |
+
+<details><summary>Example of a definition for a single tenant</summary>
+
+```
+
+curl -L -X PATCH 'http://partition.com/api/partition/v1/partitions/opendes' -H 'data-partition-id: opendes' -H 'Authorization: Bearer ...' -H 'Content-Type: application/json' --data-raw '{
+  "properties": {
+    "osm.postgres.datasource.url": {
+      "sensitive": false,
+      "value": "jdbc:postgresql://127.0.0.1:5432/postgres"
+    },
+    "osm.postgres.datasource.username": {
+      "sensitive": false,
+      "value": "postgres"
+    },
+    "osm.postgres.datasource.password": {
+      "sensitive": true,
+     "value": "<POSTGRES_PASSWORD_ENV_VARIABLE_NAME>" <- (Not actual value, just name of env variable)
+    }
+  }
+}'
+
+```
+
+</details>
+
+### Schema configuration
+
+```
+CREATE SCHEMA IF NOT EXISTS dataecosystem AUTHORIZATION <SCHEMA_POSTGRESQL_USERNAME>;
+```
+
+For private tenants:
+
+```
+-- Table: <data-partition-id>.authority
+-- DROP TABLE IF EXISTS <data-partition-id>.authority;
+CREATE TABLE IF NOT EXISTS <data-partition-id>.authority
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "Authority_pkey" PRIMARY KEY (pk),
+    CONSTRAINT authority_id UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS <data-partition-id>.authority
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: authority_datagin
+-- DROP INDEX IF EXISTS <data-partition-id>.authority_datagin;
+CREATE INDEX IF NOT EXISTS authority_datagin
+    ON <data-partition-id>.authority USING gin
+    (data)
+    TABLESPACE pg_default;
+-- Table: <data-partition-id>.entityType
+-- DROP TABLE IF EXISTS <data-partition-id>."entityType";
+CREATE TABLE IF NOT EXISTS <data-partition-id>."entityType"
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "EntityType_pkey" PRIMARY KEY (pk),
+    CONSTRAINT entitytype_id UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS <data-partition-id>."entityType"
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: entitytype_datagin
+-- DROP INDEX IF EXISTS <data-partition-id>.entitytype_datagin;
+CREATE INDEX IF NOT EXISTS entitytype_datagin
+    ON <data-partition-id>."entityType" USING gin
+    (data)
+    TABLESPACE pg_default;
+    -- Table: <data-partition-id>.schema_osm
+-- DROP TABLE IF EXISTS <data-partition-id>."schema_osm";
+CREATE TABLE IF NOT EXISTS <data-partition-id>."schema_osm"
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "Schema_pkey" PRIMARY KEY (pk),
+    CONSTRAINT schemarequest_id UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS <data-partition-id>."schema_osm"
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: schemarequest_datagin
+-- DROP INDEX IF EXISTS dataecosystem.schemarequest_datagin;
+CREATE INDEX IF NOT EXISTS schemarequest_datagin
+    ON <data-partition-id>."schema_osm" USING gin
+    (data)
+    TABLESPACE pg_default;
+    -- Table: <data-partition-id>.source
+-- DROP TABLE IF EXISTS <data-partition-id>.source;
+CREATE TABLE IF NOT EXISTS <data-partition-id>.source
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "Source_pkey" PRIMARY KEY (pk),
+    CONSTRAINT source_id UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS <data-partition-id>.source
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: source_datagin
+-- DROP INDEX IF EXISTS <data-partition-id>.source_datagin;
+CREATE INDEX IF NOT EXISTS source_datagin
+    ON <data-partition-id>.source USING gin
+    (data)
+    TABLESPACE pg_default;
+```
+
+-- For shared tenant:
+
+```
+-- Table: dataecosystem.system_authority
+-- DROP TABLE IF EXISTS dataecosystem.system_authority;
+CREATE TABLE IF NOT EXISTS dataecosystem.system_authority
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "Authority_pkey_system" PRIMARY KEY (pk),
+    CONSTRAINT authority_id_system UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS dataecosystem.system_authority
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: system_authority_datagin
+-- DROP INDEX IF EXISTS dataecosystem.system_authority_datagin;
+CREATE INDEX IF NOT EXISTS system_authority_datagin
+    ON dataecosystem.system_authority USING gin
+    (data)
+    TABLESPACE pg_default;
+-- Table: dataecosystem.system_entity_type
+-- DROP TABLE IF EXISTS dataecosystem."system_entity_type";
+CREATE TABLE IF NOT EXISTS dataecosystem."system_entity_type"
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "EntityType_pkey_system" PRIMARY KEY (pk),
+    CONSTRAINT entitytype_id_system UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS dataecosystem."system_entity_type"
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: system_entity_type_datagin
+-- DROP INDEX IF EXISTS dataecosystem.system_entity_type_datagin;
+CREATE INDEX IF NOT EXISTS system_entity_type_datagin
+    ON dataecosystem."system_entity_type" USING gin
+    (data)
+    TABLESPACE pg_default;
+    -- Table: dataecosystem.system_schema_osm
+-- DROP TABLE IF EXISTS dataecosystem."system_schema_osm";
+CREATE TABLE IF NOT EXISTS dataecosystem."system_schema_osm"
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "Schema_pkey_system" PRIMARY KEY (pk),
+    CONSTRAINT schemarequest_id_system UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS dataecosystem."system_schema_osm"
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: schemarequest_datagin
+-- DROP INDEX IF EXISTS dataecosystem.schemarequest_datagin;
+CREATE INDEX IF NOT EXISTS schemarequest_datagin
+    ON dataecosystem."system_schema_osm" USING gin
+    (data)
+    TABLESPACE pg_default;
+    -- Table: dataecosystem.system_source
+-- DROP TABLE IF EXISTS dataecosystem.system_source;
+CREATE TABLE IF NOT EXISTS dataecosystem.system_source
+(
+    id text COLLATE pg_catalog."default" NOT NULL,
+    pk bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
+    data jsonb NOT NULL,
+    CONSTRAINT "Source_pkey_system" PRIMARY KEY (pk),
+    CONSTRAINT source_id_system UNIQUE (id)
+)
+TABLESPACE pg_default;
+ALTER TABLE IF EXISTS dataecosystem.system_source
+    OWNER to <SCHEMA_POSTGRESQL_USERNAME>;
+-- Index: system_source_datagin
+-- DROP INDEX IF EXISTS dataecosystem.system_source_datagin;
+CREATE INDEX IF NOT EXISTS system_source_datagin
+    ON dataecosystem.system_source USING gin
+    (data)
+    TABLESPACE pg_default;
+```
+
+## RabbitMQ configuration
+
+### Properties set in Partition service
+
+**prefix:** `oqm.rabbitmq`
+
+It can be overridden by:
+
+- through the Spring Boot property `oqm.rabbitmq.partition-properties-prefix`
+- environment variable `OQM_RABBITMQ_PARTITION_PROPERTIES_PREFIX`
+
+**Property Set** (for two types of connection: messaging and admin operations):
+
+| Property                    | Description              |
+|-----------------------------|--------------------------|
+| oqm.rabbitmq.amqp.host      | messaging hostname or IP |
+| oqm.rabbitmq.amqp.port      | - port                   |
+| oqm.rabbitmq.amqp.path      | - path                   |
+| oqm.rabbitmq.amqp.username  | - username               |
+| oqm.rabbitmq.amqp.password  | - password               |
+| oqm.rabbitmq.admin.schema   | admin host schema        |
+| oqm.rabbitmq.admin.host     | - host name              |
+| oqm.rabbitmq.admin.port     | - port                   |
+| oqm.rabbitmq.admin.path     | - path                   |
+| oqm.rabbitmq.admin.username | - username               |
+| oqm.rabbitmq.admin.password | - password               |
+
+<details><summary>Example of a single tenant definition</summary>
+
+```
+
+curl -L -X PATCH 'https://dev.osdu.club/api/partition/v1/partitions/opendes' -H 'data-partition-id: opendes' -H 'Authorization: Bearer ...' -H 'Content-Type: application/json' --data-raw '{
+  "properties": {
+    "oqm.rabbitmq.amqp.host": {
+      "sensitive": false,
+      "value": "localhost"
+    },
+    "oqm.rabbitmq.amqp.port": {
+      "sensitive": false,
+      "value": "5672"
+    },
+    "oqm.rabbitmq.amqp.path": {
+      "sensitive": false,
+      "value": ""
+    },
+    "oqm.rabbitmq.amqp.username": {
+      "sensitive": false,
+      "value": "guest"
+    },
+    "oqm.rabbitmq.amqp.password": {
+      "sensitive": true,
+      "value": "<AMQP_PASSWORD_ENV_VARIABLE_NAME>" <- (Not actual value, just name of env variable)
+    },
+
+     "oqm.rabbitmq.admin.schema": {
+      "sensitive": false,
+      "value": "http"
+    },
+     "oqm.rabbitmq.admin.host": {
+      "sensitive": false,
+      "value": "localhost"
+    },
+    "oqm.rabbitmq.admin.port": {
+      "sensitive": false,
+      "value": "9002"
+    },
+    "oqm.rabbitmq.admin.path": {
+      "sensitive": false,
+      "value": "/api"
+    },
+    "oqm.rabbitmq.admin.username": {
+      "sensitive": false,
+      "value": "guest"
+    },
+    "oqm.rabbitmq.admin.password": {
+      "sensitive": true,
+      "value": "<AMQP_ADMIN_PASSWORD_ENV_VARIABLE_NAME>" <- (Not actual value, just name of env variable)
+    }
+  }
+}'
+
+```
+
+</details>
+
+### Exchanges & queues configuration
+
+At RabbitMq should be created exchange with name:
+
+**name:** `schema-changed`
+
+It can be overridden by:
+
+- through the Spring Boot property `schema-changed.topic-name`
+- environment variable `
+- SCHEMA_CHANGED_TOPIC_NAME`
+
+![Screenshot](./pics/rabbit.PNG)
+
+Schema service responsible for publishing only.
+Consumer side `schema-changed` topic configuration located in
+[Indexer Baremetal Rabbit documentation](https://community.opengroup.org/osdu/platform/system/indexer-service/-/blob/master/provider/indexer-gc/docs/baremetal/README.md#exchanges-and-queues-configuration)
+
+## Minio configuration
+
+### Properties set in Partition service
+
+**prefix:** `obm.minio`
+
+It can be overridden by:
+
+- through the Spring Boot property `obm.minio.partition-properties-prefix`
+- environment variable `OBM_MINIO_PARTITION_PROPERTIES_PREFIX`
+
+**Propertyset** (for two types of connection: messaging and admin operations):
+
+| Property            | Description |
+|---------------------|-------------|
+| obm.minio.endpoint  | - url       |
+| obm.minio.accessKey | - username  |
+| obm.minio.secretKey | - password  |
+
+<details><summary>Example of a single tenant definition</summary>
+
+```
+
+curl -L -X PATCH 'https://dev.osdu.club/api/partition/v1/partitions/opendes' -H 'data-partition-id: opendes' -H 'Authorization: Bearer ...' -H 'Content-Type: application/json' --data-raw '{
+  "properties": {
+    "obm.minio.endpoint": {
+      "sensitive": false,
+      "value": "localhost"
+    },
+    "obm.minio.accessKey": {
+      "sensitive": false,
+      "value": "minioadmin"
+    },
+    "obm.minio.secretKey": {
+      "sensitive": false,
+      "value": "<MINIO_SECRETKEY_ENV_VARIABLE_NAME>" <- (Not actual value, just name of env variable)
+    }
+  }
+}'
+
+```
+
+</details>
+
+### Object store configuration <a name="ObjectStoreConfig"></a>
+
+#### Used Technology
+
+MinIO (or any other supported by OBM)
+
+#### Per-tenant buckets configuration
+
+For each private tenant:
+
+These buckets must be defined in tenants’ dedicated object store servers. OBM connection properties of these servers (url, etc.) are defined as specific properties in tenants’ PartitionInfo registration objects at the Partition service as described in accordant sections of this document.
+
+<table>
+  <tr>
+   <td>Bucket Naming template
+   </td>
+   <td>Permissions required
+   </td>
+  </tr>
+  <tr>
+   <td>&lt;PartitionInfo.projectId-PartitionInfo.name>-<strong>schema</strong>
+   </td>
+   <td>ListObjects, CRUDObject
+   </td>
+  </tr>
+</table>
+
+For shared tenant only:
+
+<table>
+  <tr>
+   <td>Bucket Naming template
+   </td>
+   <td>Permissions required
+   </td>
+  </tr>
+  <tr>
+   <td>&lt;PartitionInfo.projectId-PartitionInfo.name><strong>-system-schema</strong>
+   </td>
+   <td>ListObjects, CRUDObject
+   </td>
+  </tr>
+</table>
diff --git a/schema-core-plus/docs/baremetal/pics/rabbit.PNG b/schema-core-plus/docs/baremetal/pics/rabbit.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..e1c67734b91a536659fdf0b940a93208d749e3c8
Binary files /dev/null and b/schema-core-plus/docs/baremetal/pics/rabbit.PNG differ
diff --git a/schema-core-plus/pom.xml b/schema-core-plus/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..813298cbc42ee564e1a695953f5ef679595581f4
--- /dev/null
+++ b/schema-core-plus/pom.xml
@@ -0,0 +1,185 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.opengroup.osdu</groupId>
+		<artifactId>os-schema</artifactId>
+		<version>0.25.0-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+
+	<properties>
+		<jackson-databind.version>2.15.0</jackson-databind.version>
+		<jackson.version>2.15.0</jackson.version>
+		<os-core-common.version>0.24.0</os-core-common.version>
+	</properties>
+
+	<artifactId>schema-core-plus</artifactId>
+	<description>Google cloud related implementation staff.</description>
+	<packaging>jar</packaging>
+	<version>0.25.0-SNAPSHOT</version>
+
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>com.squareup.okhttp3</groupId>
+				<artifactId>okhttp</artifactId>
+				<version>4.9.2</version>
+			</dependency>
+			<dependency>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-dependencies</artifactId>
+				<version>2.7.17</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+			<dependency>
+				<groupId>com.fasterxml.jackson</groupId>
+				<artifactId>jackson-bom</artifactId>
+				<version>2.15.0</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.opengroup.osdu</groupId>
+			<artifactId>os-core-common</artifactId>
+			<version>${os-core-common.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.opengroup.osdu</groupId>
+			<artifactId>os-schema-core</artifactId>
+			<version>0.25.0-SNAPSHOT</version>
+		</dependency>
+		<dependency>
+			<groupId>org.opengroup.osdu</groupId>
+			<artifactId>core-plus-common-lib</artifactId>
+			<version>0.24.0-rc2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-loader</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-webmvc</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-all</artifactId>
+			<version>1.10.19</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>ch.qos.logback.contrib</groupId>
+			<artifactId>logback-json-classic</artifactId>
+			<version>0.1.5</version>
+		</dependency>
+
+		<dependency>
+			<groupId>io.cucumber</groupId>
+			<artifactId>cucumber-java</artifactId>
+			<version>5.7.0</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>io.cucumber</groupId>
+			<artifactId>cucumber-junit</artifactId>
+			<version>5.7.0</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>io.cucumber</groupId>
+			<artifactId>cucumber-guice</artifactId>
+			<version>5.7.0</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>com.google.inject</groupId>
+			<artifactId>guice</artifactId>
+			<version>4.2.0</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.opengroup.osdu</groupId>
+			<artifactId>os-oqm-core</artifactId>
+			<version>0.25.0-rc1</version>
+		</dependency>
+		<dependency>
+			<groupId>org.opengroup.osdu</groupId>
+			<artifactId>os-osm-core</artifactId>
+			<version>0.25.0-rc2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.opengroup.osdu</groupId>
+			<artifactId>os-obm-core</artifactId>
+			<version>0.25.0-rc1</version>
+		</dependency>
+
+		<dependency>
+			<!-- Required for JUnit 4 tests to run -->
+			<groupId>org.junit.vintage</groupId>
+			<artifactId>junit-vintage-engine</artifactId>
+			<scope>test</scope>
+		</dependency>
+			<!--TODO used for a couple of models in TypeMapper.class, which should be removed later when clean dev env is created.-->
+		<dependency>
+			<groupId>com.google.cloud</groupId>
+			<artifactId>google-cloud-datastore</artifactId>
+			<version>2.17.5</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<version>${spring-boot-maven-plugin.version}</version>
+				<executions>
+					<execution>
+						<goals>
+							<goal>repackage</goal>
+						</goals>
+						<configuration>
+							<classifier>spring-boot</classifier>
+							<mainClass>
+								org.springframework.boot.loader.PropertiesLauncher
+							</mainClass>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+            <plugin>
+				<groupId>org.jacoco</groupId>
+				<artifactId>jacoco-maven-plugin</artifactId>
+				<version>0.8.10</version>
+				<executions>
+					<execution>
+						<goals>
+							<goal>prepare-agent</goal>
+						</goals>
+					</execution>
+					<execution>
+						<id>report</id>
+						<phase>prepare-package</phase>
+						<goals>
+							<goal>report</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/CorePlusSchemaApplication.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/CorePlusSchemaApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e0bd9bcbed646daa99d06568790342a8f7b2fec
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/CorePlusSchemaApplication.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.PropertySource;
+
+@SpringBootApplication
+@ComponentScan({"org.opengroup.osdu"})
+@ConfigurationPropertiesScan
+@PropertySource("classpath:swagger.properties")
+public class CorePlusSchemaApplication {
+
+  public static void main(String[] args) {
+    SpringApplication.run(CorePlusSchemaApplication.class, args);
+  }
+}
\ No newline at end of file
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/cache/config/CacheConfig.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/cache/config/CacheConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..009a36fbf989f9791ca4bb67d170831625d2eba5
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/cache/config/CacheConfig.java
@@ -0,0 +1,34 @@
+/*
+ *  Copyright 2020-2023 Google LLC
+ *  Copyright 2020-2023 EPAM Systems, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.cache.config;
+
+import lombok.RequiredArgsConstructor;
+import org.opengroup.osdu.core.common.cache.ICache;
+import org.opengroup.osdu.core.common.cache.VmCache;
+import org.opengroup.osdu.core.common.partition.PartitionInfo;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@RequiredArgsConstructor
+public class CacheConfig {
+  @Bean
+  public ICache<String, PartitionInfo> partitionInfoCache() {
+    return new VmCache<>(600, 2000);
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/EventMessagingPropertiesConfig.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/EventMessagingPropertiesConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..94834a57afc23efb141d26017d63dd6d9f5e71bd
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/EventMessagingPropertiesConfig.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.configuration;
+
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.ConstructorBinding;
+
+@ConfigurationProperties(prefix = "schema-changed")
+@Getter
+@ConstructorBinding
+public class EventMessagingPropertiesConfig {
+
+  private final boolean messagingEnabled;
+  private final String topicName;
+
+  public EventMessagingPropertiesConfig(boolean messagingEnabled, String topicName) {
+    if (messagingEnabled && StringUtils.isEmpty(topicName)) {
+      throw new RuntimeException("Missing event messaging configuration.");
+    }
+
+    this.messagingEnabled = messagingEnabled;
+    this.topicName = topicName;
+  }
+
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/PartitionPropertyNames.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/PartitionPropertyNames.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0f3bf6141b1bda9247eb84af3affdac3003fc8b
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/PartitionPropertyNames.java
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2020-2023 Google LLC
+ *  Copyright 2020-2023 EPAM Systems, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Setter
+@Getter
+@Configuration
+@ConfigurationProperties(prefix = "partition.properties")
+public class PartitionPropertyNames {
+
+  private String schemaBucketName;
+  private String systemSchemaBucketName;
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/PropertiesConfiguration.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/PropertiesConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..d7c57c78c75fe191708bc319fc66ff069c0a51e6
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/PropertiesConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties
+@Getter
+@Setter
+public class PropertiesConfiguration {
+
+  private String sharedTenantName;
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/mapper/TypeMapperImpl.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/mapper/TypeMapperImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..846666c9e7e80a349c02a8ba16bcacc0c9c3ba08
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/configuration/mapper/TypeMapperImpl.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.configuration.mapper;
+
+import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_SINGLETON;
+
+import com.google.cloud.Timestamp;
+import com.google.cloud.datastore.Blob;
+import com.google.cloud.datastore.Key;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import org.opengroup.osdu.core.osm.core.persistence.IdentityTranslator;
+import org.opengroup.osdu.core.osm.core.translate.Instrumentation;
+import org.opengroup.osdu.core.osm.core.translate.TypeMapper;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.model.Authority;
+import org.opengroup.osdu.schema.model.EntityType;
+import org.opengroup.osdu.schema.model.SchemaRequest;
+import org.opengroup.osdu.schema.model.Source;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Component
+@Scope(SCOPE_SINGLETON)
+public class TypeMapperImpl extends TypeMapper {
+
+  public TypeMapperImpl() {
+    super(List.of(
+        new Instrumentation<>(
+            Authority.class,
+            new HashMap<String, String>() {{
+              put("authorityId", "name");
+            }},
+            new HashMap<>(),
+            new IdentityTranslator<>(
+                Authority::getAuthorityId,
+                (a, o) -> a.setAuthorityId(((Key) o).getName())
+            ),
+            Collections.singletonList("name")
+        ),
+        new Instrumentation<>(
+            EntityType.class,
+            new HashMap<String, String>() {{
+              put("entityTypeId", "name");
+            }},
+            new HashMap<>(),
+            new IdentityTranslator<>(
+                EntityType::getEntityTypeId,
+                (et, o) -> et.setEntityTypeId(((Key) o).getName())
+            ),
+            Collections.singletonList("name")
+        ),
+        new Instrumentation<>(
+            SchemaRequest.class,
+            new HashMap<String, String>() {{
+              put("schemaVersionMajor", SchemaConstants.MAJOR_VERSION);
+              put("schemaVersionMinor", SchemaConstants.MINOR_VERSION);
+              put("schemaVersionPatch", SchemaConstants.PATCH_VERSION);
+            }},
+            new HashMap<String, Class<?>>() {{
+              put("schema", Blob.class);
+              put("dateCreated", Timestamp.class);
+            }},
+            new IdentityTranslator<>(
+                (r) -> r.getSchemaInfo().getSchemaIdentity().getId(),
+                (r, o) -> r.getSchemaInfo().getSchemaIdentity().setId(((Key) o).getName())
+            ),
+            Collections.singletonList("")
+        ),
+        new Instrumentation<>(
+            Source.class,
+            new HashMap<String, String>() {{
+              put("sourceId", "name");
+            }},
+            new HashMap<>(),
+            new IdentityTranslator<>(
+                Source::getSourceId,
+                (s, o) -> s.setSourceId(((Key) o).getName())
+            ),
+            Collections.singletonList("name")
+        )
+    ));
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/DestinationProvider.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/DestinationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ee3b46c1c6cddf3fc6acaa94a658a088a4f91ba
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/DestinationProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.destination.provider;
+
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+
+public interface DestinationProvider<DestinationT> {
+
+  /**
+   * The method used only for destinations without kind (i.e.
+   * {@link org.opengroup.osdu.oqm.core.model.OqmDestination})
+   *
+   * @param partitionId the id of partition
+   * @return the destination for OSDU Mappers
+   */
+  DestinationT getDestination(String partitionId);
+
+  /**
+   * The method used only for destinations with kind (i.e.
+   * {@link org.opengroup.osdu.core.osm.core.model.Destination}) You can also pass empty string for
+   * the kind name if you want to use this method for building other destinations
+   *
+   * @param partitionId the id of partition
+   * @param kindName    the name of the kind
+   * @return the destination for OSDU Mappers
+   */
+  DestinationT getDestination(String partitionId, String kindName);
+
+  /**
+   * The method used if tenantInfo already acknowledged and there is no need to call TenantFactory
+   * to get the info
+   *
+   * @param tenantInfo tenant info got from somewhere
+   * @param kindName   the name of the kind
+   * @return the destination for OSDU Mappers
+   */
+  DestinationT getDestination(TenantInfo tenantInfo, String kindName);
+
+  /**
+   * The method is used only for custom namespace and kind usage
+   *
+   * @param partitionId partitionId for destination
+   * @param namespace   custom namespace
+   * @param kindName    the name of the kind
+   * @return the destination for OSDU Mappers
+   */
+  DestinationT getDestination(String partitionId, String namespace, String kindName);
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/DestinationProviderImpl.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/DestinationProviderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..956ecf9909fd5b1b326055d27cf1dedcc9817dea
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/DestinationProviderImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.destination.provider;
+
+import lombok.extern.slf4j.Slf4j;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.osm.core.model.Kind;
+import org.opengroup.osdu.core.osm.core.model.Namespace;
+import org.opengroup.osdu.schema.destination.provider.model.DestinationInstructions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public abstract class DestinationProviderImpl<DestinationT> implements
+    DestinationProvider<DestinationT> {
+
+  private final ITenantFactory tenantFactory;
+
+  @Autowired
+  protected DestinationProviderImpl(ITenantFactory tenantFactory) {
+    this.tenantFactory = tenantFactory;
+  }
+
+  @Override
+  public DestinationT getDestination(String partitionId) {
+    TenantInfo tenantInfo = tenantFactory.getTenantInfo(partitionId);
+    return getDestination(tenantInfo, "");
+  }
+
+  @Override
+  public DestinationT getDestination(String partitionId, String kindName) {
+    TenantInfo tenantInfo = tenantFactory.getTenantInfo(partitionId);
+    return getDestination(tenantInfo, kindName);
+  }
+
+  @Override
+  public DestinationT getDestination(TenantInfo tenantInfo, String kindName) {
+    log.debug("Providing destination for the tenant: " + tenantInfo.getName());
+    String partitionId = tenantInfo.getDataPartitionId();
+    String namespace = tenantInfo.getName();
+    return getDestination(partitionId, namespace, kindName);
+  }
+
+  @Override
+  public DestinationT getDestination(String partitionId, String namespace, String kindName) {
+
+    DestinationInstructions instructions = DestinationInstructions.builder()
+        .dataPartition(partitionId)
+        .namespace(new Namespace(namespace))
+        .kind(new Kind(kindName))
+        .build();
+
+    return buildDestination(instructions);
+  }
+
+  protected abstract DestinationT buildDestination(DestinationInstructions instructions);
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/ObmDestinationProvider.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/ObmDestinationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0ffa7a91001d8beeac7ea2573bad30061e49595
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/ObmDestinationProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.destination.provider.impl;
+
+import static org.opengroup.osdu.schema.destination.provider.model.DestinationInstructions.toObmDestination;
+
+import lombok.extern.slf4j.Slf4j;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.obm.core.persistence.ObmDestination;
+import org.opengroup.osdu.schema.destination.provider.DestinationProviderImpl;
+import org.opengroup.osdu.schema.destination.provider.model.DestinationInstructions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+public class ObmDestinationProvider extends DestinationProviderImpl<ObmDestination> {
+
+  @Autowired
+  public ObmDestinationProvider(ITenantFactory tenantFactory) {
+    super(tenantFactory);
+  }
+
+  @Override
+  protected ObmDestination buildDestination(DestinationInstructions instructions) {
+    return toObmDestination(instructions);
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/OqmDestinationProvider.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/OqmDestinationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..de1d86ec0998fdc3d7aafaedb0af3bcd4127b0db
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/OqmDestinationProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.destination.provider.impl;
+
+import static org.opengroup.osdu.schema.destination.provider.model.DestinationInstructions.toOqmDestination;
+
+import lombok.extern.slf4j.Slf4j;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.oqm.core.model.OqmDestination;
+import org.opengroup.osdu.schema.destination.provider.DestinationProviderImpl;
+import org.opengroup.osdu.schema.destination.provider.model.DestinationInstructions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+public class OqmDestinationProvider extends DestinationProviderImpl<OqmDestination> {
+
+  @Autowired
+  public OqmDestinationProvider(ITenantFactory tenantFactory) {
+    super(tenantFactory);
+  }
+
+  @Override
+  protected OqmDestination buildDestination(DestinationInstructions instructions) {
+    return toOqmDestination(instructions);
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/OsmDestinationProvider.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/OsmDestinationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6072b6985bbdb84b75b879c53b2cbb801f3181e
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/impl/OsmDestinationProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.destination.provider.impl;
+
+import static org.opengroup.osdu.schema.destination.provider.model.DestinationInstructions.toOsmDestination;
+
+import lombok.extern.slf4j.Slf4j;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.schema.destination.provider.DestinationProviderImpl;
+import org.opengroup.osdu.schema.destination.provider.model.DestinationInstructions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class OsmDestinationProvider extends DestinationProviderImpl<Destination> {
+
+  @Autowired
+  public OsmDestinationProvider(ITenantFactory tenantFactory) {
+    super(tenantFactory);
+  }
+
+  @Override
+  protected Destination buildDestination(DestinationInstructions instructions) {
+    return toOsmDestination(instructions);
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/model/DestinationInstructions.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/model/DestinationInstructions.java
new file mode 100644
index 0000000000000000000000000000000000000000..c69b5ecafa072e567a23cdefd9e1265cefaf400f
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/destination/provider/model/DestinationInstructions.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.destination.provider.model;
+
+import lombok.Builder;
+import lombok.Data;
+import org.opengroup.osdu.core.obm.core.persistence.ObmDestination;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.Kind;
+import org.opengroup.osdu.core.osm.core.model.Namespace;
+import org.opengroup.osdu.oqm.core.model.OqmDestination;
+
+
+@Data
+@Builder
+public class DestinationInstructions {
+
+  private String dataPartition;
+  private Namespace namespace;
+  private Kind kind;
+
+  public static Destination toOsmDestination(DestinationInstructions instructions) {
+    return Destination.builder()
+        .partitionId(instructions.dataPartition)
+        .namespace(instructions.namespace)
+        .kind(instructions.kind)
+        .build();
+  }
+
+  public static OqmDestination toOqmDestination(DestinationInstructions instructions) {
+    return OqmDestination.builder()
+        .partitionId(instructions.dataPartition)
+        .build();
+  }
+
+  public static ObmDestination toObmDestination(DestinationInstructions instructions) {
+    return ObmDestination.builder()
+        .partitionId(instructions.dataPartition)
+        .build();
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/exception/AppExceptionHandler.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/exception/AppExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..6810e0ca97001a614620e83f2c4a5b09c9127ba6
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/exception/AppExceptionHandler.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.exception;
+
+import java.util.Objects;
+import lombok.extern.slf4j.Slf4j;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+@ControllerAdvice
+@Order(Ordered.HIGHEST_PRECEDENCE)
+@Slf4j
+public class AppExceptionHandler {
+
+  @ExceptionHandler(AppException.class)
+  public ResponseEntity<Object> handleAppExceptions(AppException e) {
+    return this.getErrorResponse(e);
+  }
+
+  private ResponseEntity<Object> getErrorResponse(AppException e) {
+
+    String exceptionMsg = Objects.nonNull(e.getOriginalException())
+        ? e.getOriginalException().getMessage()
+        : e.getError().getMessage();
+
+    Integer errorCode = e.getError().getCode();
+
+    if (errorCode > 499) {
+      log.error(exceptionMsg, e.getOriginalException());
+    } else {
+      log.warn(exceptionMsg, e.getOriginalException());
+    }
+
+    return new ResponseEntity<>(e.getError(), HttpStatus.resolve(errorCode));
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/messagebus/MessageBusImpl.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/messagebus/MessageBusImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a20631fd505a816c13dfe78d22ac60d37128636
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/messagebus/MessageBusImpl.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.messagebus;
+
+import com.google.gson.Gson;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import javax.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
+import org.apache.http.HttpStatus;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.oqm.core.OqmDriver;
+import org.opengroup.osdu.oqm.core.OqmDriverRuntimeException;
+import org.opengroup.osdu.oqm.core.model.OqmDestination;
+import org.opengroup.osdu.oqm.core.model.OqmMessage;
+import org.opengroup.osdu.oqm.core.model.OqmTopic;
+import org.opengroup.osdu.schema.configuration.EventMessagingPropertiesConfig;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.DestinationProvider;
+import org.opengroup.osdu.schema.impl.messagebus.model.SchemaPubSubInfo;
+import org.opengroup.osdu.schema.logging.AuditLogger;
+import org.opengroup.osdu.schema.provider.interfaces.messagebus.IMessageBus;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class MessageBusImpl implements IMessageBus {
+
+  private final OqmDriver driver;
+  private final DestinationProvider<OqmDestination> destinationProvider;
+  private final TenantInfo tenantInfo;
+
+  private final DpsHeaders headers;
+  private final EventMessagingPropertiesConfig eventMessagingPropertiesConfig;
+  private final JaxRsDpsLog logger;
+  private final AuditLogger auditLogger;
+
+  private OqmTopic oqmTopic = null;
+
+  @PostConstruct
+  void postConstruct() {
+    oqmTopic = OqmTopic.builder().name(eventMessagingPropertiesConfig.getTopicName()).build();
+  }
+
+  @Override
+  public void publishMessage(String schemaId, String eventType) {
+    if (this.eventMessagingPropertiesConfig.isMessagingEnabled()) {
+      this.logger.info(String.format("Generating event of type %s", eventType));
+
+      OqmDestination destination = destinationProvider.getDestination(headers.getPartitionId());
+      healthCheckTopic(schemaId, false);
+
+      OqmMessage message = createMessage(schemaId, eventType);
+      this.driver.publish(message, oqmTopic, destination);
+      this.auditLogger.schemaNotificationSuccess(Collections.singletonList(schemaId));
+    } else {
+      this.logger.info(SchemaConstants.SCHEMA_NOTIFICATION_IS_DISABLED);
+    }
+  }
+
+  @Override
+  public void publishMessageForSystemSchema(String schemaId, String eventType) {
+    if (this.eventMessagingPropertiesConfig.isMessagingEnabled()) {
+      OqmDestination destination = destinationProvider.getDestination(headers.getPartitionId());
+
+      healthCheckTopic(schemaId, true);
+
+      OqmMessage message = createMessage(schemaId, eventType);
+      this.driver.publish(message, oqmTopic, destination);
+      this.auditLogger.schemaNotificationSuccess(Collections.singletonList(schemaId));
+    } else {
+      this.logger.info(SchemaConstants.SCHEMA_NOTIFICATION_IS_DISABLED);
+    }
+  }
+
+  private void healthCheckTopic(String schemaId, boolean isSystemSchema) {
+    if (Objects.isNull(this.oqmTopic)) {
+      try {
+        this.oqmTopic = OqmTopic.builder().name(eventMessagingPropertiesConfig.getTopicName())
+            .build();
+      } catch (OqmDriverRuntimeException e) {
+        String errorMessage = isSystemSchema ? SchemaConstants.SYSTEM_SCHEMA_NOTIFICATION_FAILED :
+            SchemaConstants.SCHEMA_NOTIFICATION_FAILED;
+        this.logger.info(errorMessage);
+        this.auditLogger.schemaNotificationFailure(Collections.singletonList(schemaId));
+        throw new AppException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal error", errorMessage,
+            e);
+      }
+    }
+  }
+
+  private OqmMessage createMessage(String schemaId, String eventType) {
+    SchemaPubSubInfo schemaPubSubMsg = new SchemaPubSubInfo(schemaId, eventType);
+
+    String data = new Gson().toJson(Collections.singletonList(schemaPubSubMsg));
+
+    this.headers.addCorrelationIdIfMissing();
+    Map<String, String> headersMap = headers.getHeaders();
+    headersMap.put(DpsHeaders.ACCOUNT_ID, this.tenantInfo.getName());
+    headersMap.remove(DpsHeaders.AUTHORIZATION);
+
+    Map<String, String> attributes = new HashMap<>(headersMap);
+    return OqmMessage.builder()
+        .data(data)
+        .attributes(attributes)
+        .build();
+  }
+
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/messagebus/model/SchemaPubSubInfo.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/messagebus/model/SchemaPubSubInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..1644a1f57b0df601d0208d7bb7d500d0bae98f0d
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/messagebus/model/SchemaPubSubInfo.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.messagebus.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SchemaPubSubInfo {
+
+  private String kind;
+
+  private String op;
+
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmAuthorityStore.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmAuthorityStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f850817041b16ffff6262062dc602eb92c36818
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmAuthorityStore.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2020-2023 Google LLC
+ * Copyright 2020-2023 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+
+import static org.opengroup.osdu.core.osm.core.model.where.predicate.Eq.eq;
+
+import java.text.MessageFormat;
+import org.apache.commons.lang3.ObjectUtils;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.query.GetQuery;
+import org.opengroup.osdu.core.osm.core.model.where.Where;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.DestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.Authority;
+import org.opengroup.osdu.schema.provider.interfaces.schemainfostore.IAuthorityStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Repository class to register authority in KV Store using OSM
+ */
+@Repository
+public class OsmAuthorityStore implements IAuthorityStore {
+
+  private static final String SYSTEM_AUTHORITY_KIND = "system_authority";
+  private static final String NAME_FIELD = "name";
+  private final DpsHeaders headers;
+  private final DestinationProvider<Destination> destinationProvider;
+  private final JaxRsDpsLog log;
+  private final PropertiesConfiguration configuration;
+  private final Context context;
+
+  @Autowired
+  public OsmAuthorityStore(DpsHeaders headers, DestinationProvider<Destination> destinationProvider,
+      JaxRsDpsLog log, Context context,
+      PropertiesConfiguration configuration) {
+    this.headers = headers;
+    this.destinationProvider = destinationProvider;
+    this.log = log;
+    this.configuration = configuration;
+    this.context = context;
+  }
+
+  @Override
+  public Authority get(String authorityId) throws NotFoundException, ApplicationException {
+    Destination destination = getPrivateTenantDestination(this.headers.getPartitionId());
+
+    return context.findOne(buildQueryFor(destination, eq(NAME_FIELD, authorityId)))
+        .orElseThrow(() ->
+            new NotFoundException("bad input parameter"));
+  }
+
+  @Override
+  public Authority getSystemAuthority(String authorityId)
+      throws NotFoundException, ApplicationException {
+    Destination systemDestination = getSystemDestination();
+
+    return context.findOne(buildQueryFor(systemDestination, eq(NAME_FIELD, authorityId)))
+        .orElseThrow(() ->
+            new NotFoundException("bad input parameter"));
+  }
+
+  @Override
+  public Authority create(Authority authority) throws ApplicationException, BadRequestException {
+    Destination tenantDestination = getPrivateTenantDestination(this.headers.getPartitionId());
+    checkEntityExistence(authority, tenantDestination);
+
+    Authority entityFromDb;
+    try {
+      entityFromDb = context.createAndGet(authority, tenantDestination);
+    } catch (TranslatorRuntimeException ex) {
+      log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()));
+      throw new ApplicationException(SchemaConstants.INVALID_INPUT);
+    }
+    log.info(SchemaConstants.AUTHORITY_CREATED);
+    return entityFromDb;
+  }
+
+  @Override
+  public Authority createSystemAuthority(Authority authority)
+      throws ApplicationException, BadRequestException {
+    Destination systemDestination = getSystemDestination();
+    checkEntityExistence(authority, systemDestination);
+
+    Authority entityFromDb;
+    try {
+      entityFromDb = context.createAndGet(authority, systemDestination);
+    } catch (TranslatorRuntimeException ex) {
+      log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()));
+      throw new ApplicationException(SchemaConstants.INVALID_INPUT);
+    }
+    log.info(SchemaConstants.AUTHORITY_CREATED);
+    return entityFromDb;
+  }
+
+  private GetQuery<Authority> buildQueryFor(Destination destination, Where where) {
+    return new GetQuery<>(Authority.class, destination, where);
+  }
+
+  private void checkEntityExistence(Authority authority, Destination destination)
+      throws BadRequestException {
+    Authority entityFromDb =
+        context.getOne(buildQueryFor(destination, eq(NAME_FIELD, authority.getAuthorityId())));
+
+    if (ObjectUtils.isNotEmpty(entityFromDb)) {
+      log.warning(SchemaConstants.AUTHORITY_EXISTS_ALREADY_REGISTERED);
+      throw new BadRequestException(
+          MessageFormat.format(SchemaConstants.AUTHORITY_EXISTS_EXCEPTION,
+              authority.getAuthorityId()));
+    }
+  }
+
+  private Destination getPrivateTenantDestination(String partitionId) {
+    return destinationProvider.getDestination(
+        partitionId, partitionId, SchemaConstants.AUTHORITY_KIND);
+  }
+
+  private Destination getSystemDestination() {
+    return destinationProvider.getDestination(
+        configuration.getSharedTenantName(),
+        SchemaConstants.NAMESPACE,
+        SYSTEM_AUTHORITY_KIND
+    );
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmEntityTypeStore.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmEntityTypeStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..094a4e0217152e4de8e55521679c4e1292bbb04f
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmEntityTypeStore.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2020-2023 Google LLC
+ * Copyright 2020-2023 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+
+import static org.opengroup.osdu.core.osm.core.model.where.predicate.Eq.eq;
+
+import java.text.MessageFormat;
+import org.apache.commons.lang3.ObjectUtils;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.query.GetQuery;
+import org.opengroup.osdu.core.osm.core.model.where.Where;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.DestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.EntityType;
+import org.opengroup.osdu.schema.provider.interfaces.schemainfostore.IEntityTypeStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Repository class to register Entity type in KV store using OSM.
+ */
+@Repository
+public class OsmEntityTypeStore implements IEntityTypeStore {
+
+  private static final String NAME_FIELD = "name";
+  private static final String SYSTEM_ENTITY_KIND = "system_entity_type";
+  private final DpsHeaders headers;
+  private final DestinationProvider<Destination> destinationProvider;
+  private final JaxRsDpsLog log;
+  private final PropertiesConfiguration configuration;
+  private final Context context;
+
+  @Autowired
+  public OsmEntityTypeStore(DpsHeaders headers,
+      DestinationProvider<Destination> destinationProvider, JaxRsDpsLog log, Context context,
+      PropertiesConfiguration configuration) {
+    this.headers = headers;
+    this.destinationProvider = destinationProvider;
+    this.log = log;
+    this.configuration = configuration;
+    this.context = context;
+  }
+
+  @Override
+  public EntityType get(String entityTypeId) throws NotFoundException, ApplicationException {
+    Destination tenantDestination = getPrivateTenantDestination(this.headers.getPartitionId());
+
+    return context.findOne(buildQueryFor(tenantDestination, eq(NAME_FIELD, entityTypeId)))
+        .orElseThrow(() ->
+            new NotFoundException("bad input parameter"));
+  }
+
+  /**
+   * Method to get System entity type from google store
+   *
+   * @param entityTypeId
+   * @return EntityType object
+   * @throws NotFoundException
+   * @throws ApplicationException
+   */
+  @Override
+  public EntityType getSystemEntity(String entityTypeId)
+      throws NotFoundException, ApplicationException {
+    Destination systemDestination = getSystemDestination();
+
+    return context.findOne(buildQueryFor(systemDestination, eq(NAME_FIELD, entityTypeId)))
+        .orElseThrow(() ->
+            new NotFoundException("bad input parameter"));
+  }
+
+  @Override
+  public EntityType create(EntityType entityType) throws BadRequestException, ApplicationException {
+    Destination tenantDestination = getPrivateTenantDestination(this.headers.getPartitionId());
+    checkEntityExistence(entityType, tenantDestination);
+
+    EntityType entityFromDb;
+    try {
+      entityFromDb = context.createAndGet(entityType,
+          getPrivateTenantDestination(this.headers.getPartitionId()));
+    } catch (TranslatorRuntimeException ex) {
+      log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()));
+      throw new ApplicationException(SchemaConstants.INVALID_INPUT);
+    }
+    log.info(SchemaConstants.ENTITY_TYPE_CREATED);
+    return entityFromDb;
+  }
+
+  /**
+   * Method to create entityType in google store of dataPartitionId GCP
+   *
+   * @param entityType
+   * @return EntityType object
+   * @throws BadRequestException
+   * @throws ApplicationException
+   */
+  @Override
+  public EntityType createSystemEntity(EntityType entityType)
+      throws BadRequestException, ApplicationException {
+    Destination systemDestination = getSystemDestination();
+    checkEntityExistence(entityType, systemDestination);
+
+    EntityType entityFromDb;
+    try {
+      entityFromDb = context.createAndGet(entityType, systemDestination);
+    } catch (TranslatorRuntimeException ex) {
+      log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()));
+      throw new ApplicationException(SchemaConstants.INVALID_INPUT);
+    }
+    log.info(SchemaConstants.ENTITY_TYPE_CREATED);
+    return entityFromDb;
+  }
+
+  private GetQuery<EntityType> buildQueryFor(Destination destination, Where where) {
+    return new GetQuery<>(EntityType.class, destination, where);
+  }
+
+  private void checkEntityExistence(EntityType entityType, Destination destination)
+      throws BadRequestException {
+    EntityType entityFromDb = context.getOne(
+        buildQueryFor(destination, eq(NAME_FIELD, entityType.getEntityTypeId())));
+    if (ObjectUtils.isNotEmpty(entityFromDb)) {
+      log.warning(SchemaConstants.ENTITY_TYPE_EXISTS);
+      throw new BadRequestException(
+          MessageFormat.format(SchemaConstants.ENTITY_TYPE_EXISTS_EXCEPTION,
+              entityType.getEntityTypeId()));
+    }
+  }
+
+  private Destination getPrivateTenantDestination(String partitionId) {
+    return destinationProvider.getDestination(
+        partitionId, partitionId, SchemaConstants.ENTITYTYPE_KIND);
+  }
+
+  private Destination getSystemDestination() {
+    return destinationProvider.getDestination(
+        configuration.getSharedTenantName(),
+        SchemaConstants.NAMESPACE,
+        SYSTEM_ENTITY_KIND
+    );
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSchemaInfoStore.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSchemaInfoStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..74ac091e12435e6c3893addfe3d84a59ce734c76
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSchemaInfoStore.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright 2020-2023 Google LLC
+ * Copyright 2020-2023 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+import static org.opengroup.osdu.core.osm.core.model.where.condition.And.and;
+import static org.opengroup.osdu.core.osm.core.model.where.predicate.Eq.eq;
+
+import java.text.MessageFormat;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.TreeMap;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.http.HttpStatus;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.query.GetQuery;
+import org.opengroup.osdu.core.osm.core.model.where.Where;
+import org.opengroup.osdu.core.osm.core.model.where.predicate.Eq;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorException;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.DestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.QueryParams;
+import org.opengroup.osdu.schema.model.SchemaInfo;
+import org.opengroup.osdu.schema.model.SchemaRequest;
+import org.opengroup.osdu.schema.provider.interfaces.schemainfostore.ISchemaInfoStore;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Repository class to register Schema in KV store.
+ */
+
+@Repository
+public class OsmSchemaInfoStore implements ISchemaInfoStore {
+
+  private static final String SYSTEM_SCHEMA_KIND = "system_schema";
+  private static final String SCHEMA_INFO_PREFIX = "schemaInfo.%s";
+  private static final String SCHEMA_IDENTITY_PREFIX = String.format(SCHEMA_INFO_PREFIX,
+      "schemaIdentity.%s");
+  private static final String SCHEMA_ID = String.format(SCHEMA_IDENTITY_PREFIX, "id");
+  private static final String SCHEMA_OSM_KIND = String.format("%s_osm",
+      SchemaConstants.SCHEMA_KIND);
+  private static final String SYSTEM_SCHEMA_OSM_KIND = String.format("%s_osm", SYSTEM_SCHEMA_KIND);
+  private final DpsHeaders headers;
+  private final DestinationProvider<Destination> destinationProvider;
+  private final JaxRsDpsLog log;
+  private final PropertiesConfiguration configuration;
+  private final Context context;
+
+  private final ITenantFactory tenantFactory;
+
+  public OsmSchemaInfoStore(DpsHeaders headers,
+      DestinationProvider<Destination> destinationProvider, JaxRsDpsLog log,
+      PropertiesConfiguration configuration,
+      Context context, ITenantFactory tenantFactory) {
+    this.headers = headers;
+    this.destinationProvider = destinationProvider;
+    this.log = log;
+    this.configuration = configuration;
+    this.context = context;
+    this.tenantFactory = tenantFactory;
+  }
+
+  /**
+   * Method to get schemaInfo from KV store
+   *
+   * @param schemaId
+   * @return schemaInfo object
+   * @throws ApplicationException
+   * @throws NotFoundException
+   */
+  @Override
+  public SchemaInfo getSchemaInfo(String schemaId) throws ApplicationException, NotFoundException {
+    SchemaRequest schemaRequest = context.findOne(
+            buildQueryFor(getPrivateTenantDestination(this.headers.getPartitionId()),
+                eq(SCHEMA_ID, schemaId)))
+        .orElseThrow(() ->
+            new NotFoundException(SchemaConstants.SCHEMA_NOT_PRESENT));
+    return schemaRequest.getSchemaInfo();
+  }
+
+  /**
+   * Method to get System schemaInfo from KV store
+   *
+   * @param schemaId
+   * @return schemaInfo object
+   * @throws ApplicationException
+   * @throws NotFoundException
+   */
+  @Override
+  public SchemaInfo getSystemSchemaInfo(String schemaId)
+      throws ApplicationException, NotFoundException {
+    SchemaRequest schemaRequest = context.findOne(
+            buildQueryFor(getSystemDestination(), eq(SCHEMA_ID, schemaId)))
+        .orElseThrow(() ->
+            new NotFoundException(SchemaConstants.SCHEMA_NOT_PRESENT));
+    return schemaRequest.getSchemaInfo();
+  }
+
+  /**
+   * Method to Create schema in KV store of tenantId GCP
+   *
+   * @param schema
+   * @return schemaInfo object
+   * @throws ApplicationException
+   * @throws BadRequestException
+   */
+  @Override
+  public SchemaInfo createSchemaInfo(SchemaRequest schema)
+      throws ApplicationException, BadRequestException {
+    try {
+      Destination tenantDestination = getPrivateTenantDestination(this.headers.getPartitionId());
+      enrichSchemaInfo(schema.getSchemaInfo(), tenantDestination);
+
+      checkEntityExistence(schema, tenantDestination);
+
+      SchemaRequest entityFromDb;
+      try {
+        entityFromDb = context.createAndGet(schema, tenantDestination);
+
+        log.info(SchemaConstants.SCHEMA_INFO_CREATED);
+        return entityFromDb.getSchemaInfo();
+      } catch (TranslatorRuntimeException ex) {
+        log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()), ex);
+        throw new ApplicationException(SchemaConstants.INVALID_INPUT, ex);
+      }
+    } catch (ApplicationException e) {
+      throw new ApplicationException(SchemaConstants.SCHEMA_CREATION_FAILED_INVALID_OBJECT);
+    }
+  }
+
+  /**
+   * Method to Create System schema in google store
+   *
+   * @param schema
+   * @return SchemaInfo object
+   * @throws ApplicationException
+   * @throws BadRequestException
+   */
+  @Override
+  public SchemaInfo createSystemSchemaInfo(SchemaRequest schema)
+      throws ApplicationException, BadRequestException {
+    try {
+      Destination systemDestination = getSystemDestination();
+      enrichSchemaInfo(schema.getSchemaInfo(), systemDestination);
+
+      checkEntityExistence(schema, systemDestination);
+
+      SchemaRequest entityFromDb;
+      try {
+        entityFromDb = context.createAndGet(schema, systemDestination);
+      } catch (TranslatorRuntimeException ex) {
+        log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()), ex);
+        throw new ApplicationException(SchemaConstants.INVALID_INPUT, ex);
+      }
+      log.info(SchemaConstants.SCHEMA_INFO_CREATED);
+      return entityFromDb.getSchemaInfo();
+    } catch (ApplicationException e) {
+      throw new ApplicationException(SchemaConstants.SCHEMA_CREATION_FAILED_INVALID_OBJECT);
+    }
+  }
+
+  /**
+   * Method to update schema in KV store of tenantId GCP
+   *
+   * @param schema
+   * @return schemaInfo object
+   * @throws ApplicationException
+   * @throws BadRequestException
+   */
+  @Override
+  public SchemaInfo updateSchemaInfo(SchemaRequest schema)
+      throws ApplicationException, BadRequestException {
+    Destination tenantDestination = getPrivateTenantDestination(this.headers.getPartitionId());
+    enrichSchemaInfo(schema.getSchemaInfo(), tenantDestination);
+
+    SchemaRequest entityFromDb = null;
+    try {
+      entityFromDb = context.upsertAndGet(schema, tenantDestination);
+    } catch (TranslatorRuntimeException ex) {
+      log.error(SchemaConstants.OBJECT_INVALID);
+      throw new ApplicationException("Invalid object, update failed", ex);
+    }
+    log.info(SchemaConstants.SCHEMA_INFO_UPDATED);
+    return entityFromDb.getSchemaInfo();
+  }
+
+  /**
+   * Method to update System schema in KV store
+   *
+   * @param schema
+   * @return SchemaInfo object
+   * @throws ApplicationException
+   * @throws BadRequestException
+   */
+  @Override
+  public SchemaInfo updateSystemSchemaInfo(SchemaRequest schema)
+      throws ApplicationException, BadRequestException {
+    Destination systemDestination = getSystemDestination();
+    enrichSchemaInfo(schema.getSchemaInfo(), systemDestination);
+
+    SchemaRequest entityFromDb = null;
+    try {
+      entityFromDb = context.upsertAndGet(schema, systemDestination);
+    } catch (TranslatorRuntimeException ex) {
+      log.error(SchemaConstants.OBJECT_INVALID);
+      throw new ApplicationException("Invalid object, update failed", ex);
+    }
+    log.info(SchemaConstants.SCHEMA_INFO_UPDATED);
+    return entityFromDb.getSchemaInfo();
+  }
+
+  /**
+   * Method to clean schemaInfo in google datastore of tenantId GCP
+   *
+   * @param schemaId
+   * @return status
+   * @throws ApplicationException
+   */
+  @Override
+  public boolean cleanSchema(String schemaId) throws ApplicationException {
+    try {
+      context.delete(SchemaRequest.class,
+          getPrivateTenantDestination(this.headers.getPartitionId()), eq(SCHEMA_ID, schemaId));
+      return true;
+    } catch (TranslatorException ex) {
+      return false;
+    }
+  }
+
+  /**
+   * Method to clean System schemaInfo in google datastore
+   *
+   * @param schemaId
+   * @return status
+   * @throws ApplicationException
+   */
+  @Override
+  public boolean cleanSystemSchema(String schemaId) throws ApplicationException {
+    try {
+      context.delete(SchemaRequest.class, getSystemDestination(), eq(SCHEMA_ID, schemaId));
+      return true;
+    } catch (TranslatorException ex) {
+      return false;
+    }
+  }
+
+  @Override
+  public String getLatestMinorVerSchema(SchemaInfo schemaInfo) throws ApplicationException {
+    GetQuery<SchemaRequest> getQuery = new GetQuery<>(SchemaRequest.class,
+        getPrivateTenantDestination(this.headers.getPartitionId()),
+        and(
+            eq(String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.AUTHORITY),
+                schemaInfo.getSchemaIdentity().getAuthority()),
+            eq(String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.ENTITY_TYPE),
+                schemaInfo.getSchemaIdentity().getEntityType()),
+            eq(String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.MAJOR_VERSION),
+                schemaInfo.getSchemaIdentity().getSchemaVersionMajor()),
+            eq(String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.SOURCE),
+                schemaInfo.getSchemaIdentity().getSource())
+        ));
+
+    List<SchemaRequest> results = context.getResultsAsList(getQuery);
+
+    Iterator<SchemaRequest> result = results.iterator();
+
+    TreeMap<Long, Object> sortedMap = new TreeMap<>(Collections.reverseOrder());
+    while (result.hasNext()) {
+      SchemaRequest entity = result.next();
+      sortedMap.put(
+          entity.getSchemaInfo().getSchemaIdentity().getSchemaVersionMinor(),
+          entity.getSchema());
+    }
+    if (sortedMap.size() != 0) {
+      Entry<Long, Object> entry = sortedMap.firstEntry();
+      return String.valueOf(entry.getValue());
+    }
+    return "";
+  }
+
+  @Override
+  public List<SchemaInfo> getSchemaInfoList(QueryParams queryParams, String tenantId)
+      throws ApplicationException {
+    List<SchemaInfo> schemaList = new LinkedList<>();
+    List<Eq> filterList = getFilters(queryParams);
+
+    GetQuery<SchemaRequest>.GetQueryBuilder<SchemaRequest> queryBuilder = new GetQuery<>(
+        SchemaRequest.class, this.getPrivateTenantDestination(
+        headers.getPartitionId())).builder();
+    if (!filterList.isEmpty()) {
+      queryBuilder.where(buildFiltersFromList(filterList));
+    }
+    for (SchemaRequest entity : context.getResultsAsList(queryBuilder.build())) {
+      schemaList.add(entity.getSchemaInfo());
+    }
+
+    return schemaList;
+  }
+
+  /**
+   * Get schema info list for system schemas
+   *
+   * @param queryParams
+   * @return
+   * @throws ApplicationException
+   */
+  @Override
+  public List<SchemaInfo> getSystemSchemaInfoList(QueryParams queryParams)
+      throws ApplicationException {
+    List<SchemaInfo> schemaList = new LinkedList<>();
+    List<Eq> filterList = getFilters(queryParams);
+
+    GetQuery<SchemaRequest>.GetQueryBuilder<SchemaRequest> queryBuilder = new GetQuery<>(
+        SchemaRequest.class, getSystemDestination()).builder();
+    if (!filterList.isEmpty()) {
+      queryBuilder.where(buildFiltersFromList(filterList));
+    }
+    for (SchemaRequest entity : context.getResultsAsList(queryBuilder.build())) {
+      schemaList.add(entity.getSchemaInfo());
+    }
+
+    return schemaList;
+  }
+
+  /**
+   * Method to check whether given system schema id is unique or not in system schemas and current
+   * private tenant only*
+   *
+   * @param schemaId
+   * @param tenantId
+   * @return
+   */
+  @Override
+  public boolean isUnique(String schemaId, String tenantId) {
+    try {
+      GetQuery<SchemaRequest> systemSchemasQuery = buildQueryFor(getSystemDestination(),
+          eq(SCHEMA_ID, schemaId));
+      List<SchemaRequest> systemSchemasResult = context.getResultsAsList(systemSchemasQuery);
+      if (!systemSchemasResult.isEmpty()) {
+        return false;
+      }
+      GetQuery<SchemaRequest> privateTenantSchemasQuery =
+          buildQueryFor(getPrivateTenantDestination(this.headers.getPartitionId()),
+              eq(SCHEMA_ID, schemaId));
+      List<SchemaRequest> privateSchemasResult = context.getResultsAsList(
+          privateTenantSchemasQuery);
+      if (!privateSchemasResult.isEmpty()) {
+        return false;
+      }
+    } catch (TranslatorRuntimeException e) {
+      throw new AppException(HttpStatus.SC_BAD_REQUEST, "Schema uniqueness check failed",
+          String.format("Misconfigured tenant-info for %s, not possible to check schema uniqueness",
+              tenantId), e);
+    }
+    return true;
+  }
+
+  /**
+   * Method to check whether given system schema id is unique or not in system schemas and in all
+   * private tenants
+   *
+   * @param schemaId
+   * @return
+   * @throws ApplicationException
+   */
+  @Override
+  public boolean isUniqueSystemSchema(String schemaId) {
+    GetQuery<SchemaRequest> systemSchemasQuery = buildQueryFor(getSystemDestination(),
+        eq(SCHEMA_ID, schemaId));
+    List<SchemaRequest> systemSchemasResult = context.getResultsAsList(systemSchemasQuery);
+    if (!systemSchemasResult.isEmpty()) {
+      return false;
+    }
+
+    List<String> privateTenantList = tenantFactory.listTenantInfo().stream()
+        .map(TenantInfo::getDataPartitionId)
+        .toList();
+
+    for (String tenant : privateTenantList) {
+      GetQuery<SchemaRequest> query = buildQueryFor(getPrivateTenantDestination(tenant),
+          eq(SCHEMA_ID, schemaId));
+      try {
+        List<SchemaRequest> schemas = context.getResultsAsList(query);
+        if (!schemas.isEmpty()) {
+          return false;
+        }
+      } catch (TranslatorRuntimeException e) {
+        throw new AppException(HttpStatus.SC_BAD_REQUEST, "Schema uniqueness check failed",
+            String.format(
+                "Misconfigured tenant-info for %s, not possible to check schema uniqueness",
+                tenant), e);
+      }
+    }
+    return true;
+  }
+
+  private Where buildFiltersFromList(List<Eq> filters) {
+    return filters.size() > 1
+        ? and(filters.get(0), filters.get(1), filters.toArray(filters.toArray(new Where[0])))
+        : filters.get(0);
+
+  }
+
+  private void enrichSchemaInfo(SchemaInfo schema, Destination destination)
+      throws BadRequestException {
+    if (schema.getSupersededBy() != null) {
+      Optional<SchemaRequest> superseded =
+          context.findOne(
+              buildQueryFor(destination, eq(SCHEMA_ID, schema.getSupersededBy().getId())));
+
+      if (schema.getSupersededBy().getId() == null
+          || !superseded.isPresent()) {
+        log.error(SchemaConstants.INVALID_SUPERSEDEDBY_ID);
+        throw new BadRequestException(SchemaConstants.INVALID_SUPERSEDEDBY_ID);
+      }
+    }
+
+    schema.setDateCreated(Date.from(Instant.now()));
+    schema.setCreatedBy(headers.getUserEmail());
+  }
+
+  private List<Eq> getFilters(QueryParams queryParams) {
+    List<Eq> filterList = new LinkedList<>();
+    if (queryParams.getAuthority() != null) {
+      filterList.add(eq(
+          String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.AUTHORITY),
+          queryParams.getAuthority()));
+    }
+    if (queryParams.getSource() != null) {
+      filterList.add(eq(
+          String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.SOURCE),
+          queryParams.getSource()));
+    }
+    if (queryParams.getEntityType() != null) {
+      filterList.add(eq(
+          String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.ENTITY_TYPE),
+          queryParams.getEntityType()));
+    }
+    if (queryParams.getSchemaVersionMajor() != null) {
+      filterList.add(eq(
+          String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.MAJOR_VERSION),
+          queryParams.getSchemaVersionMajor()));
+    }
+    if (queryParams.getSchemaVersionMinor() != null) {
+      filterList.add(eq(
+          String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.MINOR_VERSION),
+          queryParams.getSchemaVersionMinor()));
+    }
+    if (queryParams.getSchemaVersionPatch() != null) {
+      filterList.add(eq(
+          String.format(SCHEMA_IDENTITY_PREFIX, SchemaConstants.PATCH_VERSION),
+          queryParams.getSchemaVersionPatch()));
+    }
+    if (queryParams.getStatus() != null) {
+      filterList.add(eq(
+          String.format(SCHEMA_INFO_PREFIX, SchemaConstants.STATUS),
+          queryParams.getStatus().toUpperCase()));
+    }
+    return filterList;
+  }
+
+  private Destination getPrivateTenantDestination(String partitionId) {
+    return destinationProvider.getDestination(
+        partitionId,
+        partitionId,
+        SCHEMA_OSM_KIND
+    );
+  }
+
+  private Destination getSystemDestination() {
+    return destinationProvider.getDestination(
+        configuration.getSharedTenantName(),
+        SchemaConstants.NAMESPACE,
+        SYSTEM_SCHEMA_OSM_KIND
+    );
+  }
+
+  private GetQuery<SchemaRequest> buildQueryFor(Destination destination, Where where) {
+    return new GetQuery<>(SchemaRequest.class, destination, where);
+  }
+
+  private void checkEntityExistence(SchemaRequest entity, Destination destination)
+      throws BadRequestException {
+    SchemaRequest entityFromDb = context.getOne(buildQueryFor(destination,
+        eq(SCHEMA_ID, entity.getSchemaInfo().getSchemaIdentity().getId())));
+    if (ObjectUtils.isNotEmpty(entityFromDb)) {
+      log.warning(SchemaConstants.SCHEMA_CREATION_FAILED);
+      throw new BadRequestException(MessageFormat.format(SchemaConstants.SCHEMA_ID_EXISTS,
+          entity.getSchemaInfo().getSchemaIdentity().getId()));
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSourceStore.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSourceStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..5dca87277e02c52aeaf0094bb6ecc559db5d3606
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSourceStore.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2020-2023 Google LLC
+ * Copyright 2020-2023 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+
+import static org.opengroup.osdu.core.osm.core.model.where.predicate.Eq.eq;
+
+import java.text.MessageFormat;
+import org.apache.commons.lang3.ObjectUtils;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.query.GetQuery;
+import org.opengroup.osdu.core.osm.core.model.where.Where;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.DestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.Source;
+import org.opengroup.osdu.schema.provider.interfaces.schemainfostore.ISourceStore;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Repository class to register Source in KV store.
+ */
+@Repository
+public class OsmSourceStore implements ISourceStore {
+
+  private static final String NAME_FIELD = "name";
+  private static final String SYSTEM_SOURCE_KIND = "system_source";
+  private final DpsHeaders headers;
+  private final DestinationProvider<Destination> destinationProvider;
+  private final JaxRsDpsLog log;
+  private final PropertiesConfiguration configuration;
+  private final Context context;
+
+  public OsmSourceStore(DpsHeaders headers,
+      DestinationProvider<Destination> destinationProvider, JaxRsDpsLog log,
+      PropertiesConfiguration configuration,
+      Context context) {
+    this.headers = headers;
+    this.destinationProvider = destinationProvider;
+    this.log = log;
+    this.configuration = configuration;
+    this.context = context;
+  }
+
+  @Override
+  public Source get(String sourceId) throws NotFoundException, ApplicationException {
+    Destination tenantDestination = getPrivateTenantDestination(this.headers.getPartitionId());
+
+    return context.findOne(buildQueryFor(tenantDestination, eq(NAME_FIELD, sourceId)))
+        .orElseThrow(() ->
+            new NotFoundException("bad input parameter"));
+  }
+
+  /**
+   * Method to get System Source in KV store
+   *
+   * @param sourceId
+   * @return Source object
+   * @throws NotFoundException
+   * @throws ApplicationException
+   */
+  @Override
+  public Source getSystemSource(String sourceId) throws NotFoundException, ApplicationException {
+    Destination systemDestination = getSystemDestination();
+
+    return context.findOne(buildQueryFor(systemDestination, eq(NAME_FIELD, sourceId)))
+        .orElseThrow(() ->
+            new NotFoundException("bad input parameter"));
+  }
+
+  @Override
+  public Source create(Source source) throws BadRequestException, ApplicationException {
+    Destination tenantDestination = getPrivateTenantDestination(this.headers.getPartitionId());
+    checkEntityExistence(source, tenantDestination);
+
+    Source entityFromDb;
+    try {
+      entityFromDb = context.createAndGet(source, tenantDestination);
+    } catch (TranslatorRuntimeException ex) {
+      log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()));
+      throw new ApplicationException(SchemaConstants.INVALID_INPUT);
+    }
+    log.info(SchemaConstants.SOURCE_CREATED);
+    return entityFromDb;
+  }
+
+  /**
+   * Method to create System Source in KV store
+   *
+   * @param source
+   * @return Source object
+   * @throws BadRequestException
+   * @throws ApplicationException
+   */
+  @Override
+  public Source createSystemSource(Source source) throws BadRequestException, ApplicationException {
+    Destination systemDestination = getSystemDestination();
+    checkEntityExistence(source, systemDestination);
+
+    Source entityFromDb;
+    try {
+      entityFromDb = context.createAndGet(source, systemDestination);
+    } catch (TranslatorRuntimeException ex) {
+      log.error(MessageFormat.format(SchemaConstants.OBJECT_INVALID, ex.getMessage()));
+      throw new ApplicationException(SchemaConstants.INVALID_INPUT);
+    }
+    log.info(SchemaConstants.SOURCE_CREATED);
+    return entityFromDb;
+  }
+
+  private Destination getPrivateTenantDestination(String partitionId) {
+    return destinationProvider.getDestination(
+        partitionId, partitionId, SchemaConstants.SOURCE_KIND);
+  }
+
+  private Destination getSystemDestination() {
+    return destinationProvider.getDestination(
+        configuration.getSharedTenantName(),
+        SchemaConstants.NAMESPACE,
+        SYSTEM_SOURCE_KIND
+    );
+  }
+
+  private GetQuery<Source> buildQueryFor(Destination destination, Where where) {
+    return new GetQuery<>(Source.class, destination, where);
+  }
+
+  private void checkEntityExistence(Source source, Destination destination)
+      throws BadRequestException {
+    Source entityFromDb = context.getOne(
+        buildQueryFor(destination, eq(NAME_FIELD, source.getSourceId())));
+
+    if (ObjectUtils.isNotEmpty(entityFromDb)) {
+      log.warning(SchemaConstants.SOURCE_EXISTS);
+      throw new BadRequestException(
+          MessageFormat.format(SchemaConstants.SOURCE_EXISTS_EXCEPTION, source.getSourceId()));
+    }
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemastore/ObmSchemaStore.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemastore/ObmSchemaStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..d494d93b4516be85708de87577581fc7291c0639
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/impl/schemastore/ObmSchemaStore.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.schemastore;
+
+
+import static org.opengroup.osdu.core.obm.core.S3CompatibleErrors.NO_SUCH_KEY;
+
+import java.nio.charset.StandardCharsets;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.obm.core.Driver;
+import org.opengroup.osdu.core.obm.core.ObmDriverRuntimeException;
+import org.opengroup.osdu.core.obm.core.model.Blob;
+import org.opengroup.osdu.core.obm.core.persistence.ObmDestination;
+import org.opengroup.osdu.schema.configuration.PartitionPropertyNames;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.DestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.provider.interfaces.schemastore.ISchemaStore;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Repository class to register resolved Schema in Blob storage.
+ */
+@Repository
+public class ObmSchemaStore implements ISchemaStore {
+
+  private static final String SCHEMA_BUCKET_EXTENSION = "-system-schema";
+  private final ITenantFactory tenantFactory;
+  private final DpsHeaders headers;
+  private final DestinationProvider<ObmDestination> destinationProvider;
+  private final JaxRsDpsLog log;
+  private final PropertiesConfiguration configuration;
+  private final Driver driver;
+  private final PartitionPropertyNames partitionPropertyNames;
+  private final PartitionPropertyResolver partitionPropertyResolver;
+
+  public ObmSchemaStore(ITenantFactory tenantFactory, DpsHeaders headers,
+      DestinationProvider<ObmDestination> destinationProvider, JaxRsDpsLog log,
+      PropertiesConfiguration configuration,
+      Driver driver, PartitionPropertyNames partitionPropertyNames,
+      PartitionPropertyResolver partitionPropertyResolver) {
+    this.tenantFactory = tenantFactory;
+    this.headers = headers;
+    this.destinationProvider = destinationProvider;
+    this.log = log;
+    this.configuration = configuration;
+    this.driver = driver;
+    this.partitionPropertyNames = partitionPropertyNames;
+    this.partitionPropertyResolver = partitionPropertyResolver;
+  }
+
+  /**
+   * Method to get schema from Blob Storage given Tenant ProjectInfo
+   *
+   * @param dataPartitionId
+   * @param filePath
+   * @return schema object
+   * @throws ApplicationException
+   * @throws NotFoundException
+   */
+  @Override
+  public String getSchema(String dataPartitionId, String filePath)
+      throws ApplicationException, NotFoundException {
+    filePath = filePath + SchemaConstants.JSON_EXTENSION;
+    String bucketName = getSchemaBucketName(dataPartitionId);
+
+    byte[] blob = null;
+
+    try {
+      blob = driver.getBlobContent(bucketName, filePath,
+          getDestination(this.headers.getPartitionId()));
+    } catch (ObmDriverRuntimeException | NullPointerException ex) {
+      if (isNotFoundException(ex)) {
+        log.warning(ex.getMessage());
+        throw new NotFoundException(SchemaConstants.SCHEMA_NOT_PRESENT);
+      } else {
+        throw new ApplicationException(SchemaConstants.INTERNAL_SERVER_ERROR);
+      }
+    }
+
+    if (blob != null) {
+      return new String(blob, StandardCharsets.UTF_8);
+    }
+    throw new NotFoundException(SchemaConstants.SCHEMA_NOT_PRESENT);
+  }
+
+  private boolean isNotFoundException(RuntimeException ex) {
+    if (ex instanceof NullPointerException) {
+      return true;
+    }
+
+    ObmDriverRuntimeException obmException = (ObmDriverRuntimeException) ex;
+
+    if (obmException.getCause() instanceof IllegalArgumentException) {
+      return NO_SUCH_KEY.equals(obmException.getError());
+    }
+
+    return false;
+  }
+
+  /**
+   * Method to get System schema from Blob Storage
+   *
+   * @param filePath
+   * @return Schema object
+   * @throws NotFoundException
+   * @throws ApplicationException
+   */
+  @Override
+  public String getSystemSchema(String filePath) throws NotFoundException, ApplicationException {
+    filePath = filePath + SchemaConstants.JSON_EXTENSION;
+    String systemSchemaBucketName = getSystemSchemaBucketName();
+
+    byte[] blob = null;
+
+    try {
+      blob = driver.getBlobContent(systemSchemaBucketName, filePath, getSystemDestination());
+    } catch (ObmDriverRuntimeException | NullPointerException ex) {
+      if (isNotFoundException(ex)) {
+        log.warning(ex.getMessage());
+        throw new NotFoundException(SchemaConstants.SCHEMA_NOT_PRESENT);
+      } else {
+        throw new ApplicationException(SchemaConstants.INTERNAL_SERVER_ERROR);
+      }
+    }
+
+    if (blob != null) {
+      return new String(blob, StandardCharsets.UTF_8);
+    }
+    throw new NotFoundException(SchemaConstants.SCHEMA_NOT_PRESENT);
+  }
+
+  /**
+   * Method to write schema to Blob Storage given Tenant ProjectInfo
+   *
+   * @param filePath
+   * @param content
+   * @return schema object
+   * @throws ApplicationException
+   */
+
+  @Override
+  public String createSchema(String filePath, String content) throws ApplicationException {
+    String dataPartitionId = headers.getPartitionId();
+    filePath = filePath + SchemaConstants.JSON_EXTENSION;
+    String bucketName = getSchemaBucketName(dataPartitionId);
+
+    Blob blob = Blob.builder()
+        .bucket(bucketName)
+        .name(filePath)
+        .build();
+
+    try {
+      Blob blobFromStorage = driver.createAndGetBlob(blob, content.getBytes(StandardCharsets.UTF_8),
+          getDestination(this.headers.getPartitionId()));
+      log.info(SchemaConstants.SCHEMA_CREATED);
+      return blobFromStorage.getName();
+    } catch (ObmDriverRuntimeException ex) {
+      throw new ApplicationException(SchemaConstants.INTERNAL_SERVER_ERROR);
+    }
+  }
+
+  /**
+   * Method to write System schema to Blob Storage
+   *
+   * @param filePath
+   * @param content
+   * @return schema object
+   * @throws ApplicationException
+   */
+  @Override
+  public String createSystemSchema(String filePath, String content) throws ApplicationException {
+    filePath = filePath + SchemaConstants.JSON_EXTENSION;
+    String systemSchemaBucketName = getSystemSchemaBucketName();
+
+    Blob blob = Blob.builder()
+        .bucket(systemSchemaBucketName)
+        .name(filePath)
+        .build();
+
+    try {
+      Blob blobFromStorage = driver.createAndGetBlob(blob, content.getBytes(StandardCharsets.UTF_8),
+          getSystemDestination());
+      log.info(SchemaConstants.SCHEMA_CREATED);
+      return blobFromStorage.getName();
+    } catch (ObmDriverRuntimeException ex) {
+      throw new ApplicationException(SchemaConstants.INTERNAL_SERVER_ERROR);
+    }
+  }
+
+  @Override
+  public boolean cleanSchemaProject(String schemaId) {
+    String dataPartitionId = headers.getPartitionId();
+    String fileName = schemaId + SchemaConstants.JSON_EXTENSION;
+    String bucketName = getSchemaBucketName(dataPartitionId);
+    return driver.deleteBlob(bucketName, fileName, getDestination(this.headers.getPartitionId()));
+  }
+
+  /**
+   * Method to clean System schema from Blob Storage
+   *
+   * @param schemaId
+   * @return
+   * @throws ApplicationException
+   */
+  @Override
+  public boolean cleanSystemSchemaProject(String schemaId) {
+    String fileName = schemaId + SchemaConstants.JSON_EXTENSION;
+    String systemSchemaBucketName = getSystemSchemaBucketName();
+    return driver.deleteBlob(systemSchemaBucketName, fileName, getSystemDestination());
+  }
+
+  private String getSchemaBucketName(String dataPartitionId) {
+    return partitionPropertyResolver.getOptionalPropertyValue(
+        partitionPropertyNames.getSchemaBucketName(), dataPartitionId).orElseGet(() -> {
+      TenantInfo tenantInfo = tenantFactory.getTenantInfo(dataPartitionId);
+      return String.format("%s-%s%s", tenantInfo.getProjectId(), tenantInfo.getName(),
+          SchemaConstants.SCHEMA_BUCKET_EXTENSION);
+    });
+  }
+
+  private String getSystemSchemaBucketName() {
+    return partitionPropertyResolver.getOptionalPropertyValue(
+            partitionPropertyNames.getSystemSchemaBucketName(), configuration.getSharedTenantName())
+        .orElseGet(() -> {
+          TenantInfo tenantInfo = tenantFactory.getTenantInfo(configuration.getSharedTenantName());
+          return String.format("%s-%s%s", tenantInfo.getProjectId(), tenantInfo.getName(),
+              SCHEMA_BUCKET_EXTENSION);
+        });
+  }
+
+  private ObmDestination getDestination(String partitionId) {
+    return destinationProvider.getDestination(partitionId);
+  }
+
+  private ObmDestination getSystemDestination() {
+    return destinationProvider.getDestination(configuration.getSharedTenantName());
+  }
+
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/security/AuthorizationServiceForServiceAdminImpl.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/security/AuthorizationServiceForServiceAdminImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f81e11d96db025ab6be33011b1227f9d081e0f3
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/security/AuthorizationServiceForServiceAdminImpl.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.security;
+
+import static org.opengroup.osdu.core.common.model.http.DpsHeaders.DATA_PARTITION_ID;
+
+import java.util.Objects;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.opengroup.osdu.core.common.model.entitlements.AuthorizationResponse;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.provider.interfaces.IAuthorizationService;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.provider.interfaces.authorization.IAuthorizationServiceForServiceAdmin;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.annotation.RequestScope;
+
+@Slf4j
+@Component
+@RequestScope
+@RequiredArgsConstructor
+public class AuthorizationServiceForServiceAdminImpl implements
+    IAuthorizationServiceForServiceAdmin {
+
+  private final DpsHeaders headers;
+  private static final String WORKFLOW_SYSTEM_ADMIN = "service.schema-service.system-admin";
+  private final PropertiesConfiguration configuration;
+  private final IAuthorizationService authorizationService;
+
+  @Override
+  public boolean isDomainAdminServiceAccount() {
+    if (Objects.isNull(headers.getAuthorization()) || headers.getAuthorization().isEmpty()) {
+      throw AppException.createUnauthorized("No JWT token. Access is Forbidden");
+    }
+    this.headers.put(DATA_PARTITION_ID, configuration.getSharedTenantName());
+    AuthorizationResponse authResponse =
+        authorizationService.authorizeAny(headers, WORKFLOW_SYSTEM_ADMIN);
+    headers.put(DpsHeaders.USER_EMAIL, authResponse.getUser());
+    return true;
+  }
+}
diff --git a/schema-core-plus/src/main/java/org/opengroup/osdu/schema/security/WebSecurity.java b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/security/WebSecurity.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdae6ccbaeed3e8312c8f620afa5f2077df34c6e
--- /dev/null
+++ b/schema-core-plus/src/main/java/org/opengroup/osdu/schema/security/WebSecurity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.security;
+
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurity extends WebSecurityConfigurerAdapter {
+
+  @Override
+  protected void configure(HttpSecurity http) throws Exception {
+    http.httpBasic().disable().csrf()
+        .disable(); // disable default authN. AuthN handled by endpoints proxy
+  }
+}
diff --git a/schema-core-plus/src/main/resources/application.properties b/schema-core-plus/src/main/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..c0c16ade5bff694d38e6d05951ed363801f30e6c
--- /dev/null
+++ b/schema-core-plus/src/main/resources/application.properties
@@ -0,0 +1,44 @@
+# Server config
+server.servlet.context-path=/api/schema-service/v1
+server.port=8080
+
+# Log config
+logging.level.org.springframework.web=${LOG_LEVEL:INFO}
+LOG_PREFIX=schema
+
+# disabling default spring actuator endpoint
+management.health.elasticsearch.enabled=false
+management.endpoints.web.base-path=/
+management.endpoints.web.path-mapping.health=health
+management.endpoint.info.enabled=false
+
+# Core-common config
+propertyResolver.strategy=partition
+
+# Partition properties config
+partition.properties.schema-bucket-name=schema.bucket.name
+partition.properties.system-schema-bucket-name=system.schema.bucket.name
+
+# Service level config
+
+## Use this property to name your shared tenant name
+shared-tenant-name=${SHARED_TENANT_NAME:osdu}
+
+## Status messaging switch
+schema-changed.messaging-enabled=${SCHEMA_CHANGED_MESSAGING_ENABLED:true}
+## Status messaging target topic
+schema-changed.topic-name=${SCHEMA_CHANGED_TOPIC_NAME:schema-changed}
+
+## not used variable must be set with a placeholder to avoid application run failure
+AUTHORIZE_API_KEY=placeholder
+
+# External services config
+ENTITLEMENTS_HOST=http://entitlements
+ENTITLEMENTS_PATH=/api/entitlements/v2
+AUTHORIZE_API=${ENTITLEMENTS_HOST}${ENTITLEMENTS_PATH}
+
+PARTITION_HOST=http://partition
+PARTITION_PATH=/api/partition/v1
+PARTITION_API=${PARTITION_HOST}${PARTITION_PATH}
+
+partition-auth-enabled=false
\ No newline at end of file
diff --git a/schema-core-plus/src/main/resources/logback.xml b/schema-core-plus/src/main/resources/logback.xml
new file mode 100644
index 0000000000000000000000000000000000000000..699e690c0541368723e891d07c466daa60df2951
--- /dev/null
+++ b/schema-core-plus/src/main/resources/logback.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+  <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+  <logger name="org.opengroup.osdu" level="DEBUG"/>
+  <springProfile name="local">
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+      <encoder>
+        <pattern>%yellow([%thread]) %highlight(| %-5level |) %green(%d) %cyan(| %logger{15} |) %highlight(%msg) %n</pattern>
+        <charset>utf8</charset>
+      </encoder>
+    </appender>
+    <root level="info">
+      <appender-ref ref="CONSOLE"/>
+    </root>
+  </springProfile>
+
+  <springProfile name="!local">
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+      <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
+        <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
+          <timestampFormat>yyyy-MM-dd HH:mm:ss.SSS</timestampFormat>
+          <timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
+          <appendLineSeparator>true</appendLineSeparator>
+        </layout>
+      </encoder>
+    </appender>
+
+    <root level="info">
+      <appender-ref ref="stdout"/>
+    </root>
+  </springProfile>
+
+</configuration>
\ No newline at end of file
diff --git a/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/messagebus/MessageBusImplTest.java b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/messagebus/MessageBusImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a75fc537557db77712f3b23f6317251ccf53afb8
--- /dev/null
+++ b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/messagebus/MessageBusImplTest.java
@@ -0,0 +1,101 @@
+/*
+  Copyright 2021 Google LLC
+  Copyright 2021 EPAM Systems, Inc
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+package org.opengroup.osdu.schema.impl.messagebus;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+
+import org.opengroup.osdu.oqm.core.OqmDriver;
+import org.opengroup.osdu.oqm.core.model.OqmMessage;
+import org.opengroup.osdu.oqm.core.model.OqmTopic;
+import org.opengroup.osdu.schema.configuration.EventMessagingPropertiesConfig;
+import org.opengroup.osdu.schema.destination.provider.impl.OqmDestinationProvider;
+import org.opengroup.osdu.schema.logging.AuditLogger;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MessageBusImplTest {
+
+  private static final String SCHEMA_ID = "schemaId";
+  private static final String EVENT_TYPE = "eventType";
+  private static final String TENANT_NAME = "tenantName";
+  private static final String DATA_PARTITION_ID = "partitionId";
+  private static final String CORRELATION_ID = "correlationId";
+
+  @Mock
+  private OqmTopic oqmTopic;
+
+  @Mock
+  private OqmDriver driver;
+
+  @Mock
+  private TenantInfo tenantInfo;
+
+  @Mock
+  private DpsHeaders headers;
+
+  @Mock
+  private OqmDestinationProvider destinationProvider;
+
+  @Mock
+  private EventMessagingPropertiesConfig eventMessagingPropertiesConfig;
+
+  @Mock
+  private JaxRsDpsLog logger;
+
+  @Mock
+  private AuditLogger auditLogger;
+
+  @InjectMocks
+  private MessageBusImpl sut;
+
+  @Test
+  public void shouldNot_publishEventMessage_WhenFlagIsFalse() {
+    when(this.eventMessagingPropertiesConfig.isMessagingEnabled()).thenReturn(false);
+
+    this.sut.publishMessage(SCHEMA_ID, EVENT_TYPE);
+
+    verify(this.driver, never()).publish(any(OqmMessage.class), any(), any());
+  }
+
+  @Test
+  public void should_publishEventMessage_WhenFlagIsTrue() {
+    when(this.eventMessagingPropertiesConfig.isMessagingEnabled()).thenReturn(true);
+    when(this.tenantInfo.getName()).thenReturn(TENANT_NAME);
+    HashMap<String, String> headersMap = new HashMap<>();
+    headersMap.put(DpsHeaders.DATA_PARTITION_ID, DATA_PARTITION_ID);
+    headersMap.put(DpsHeaders.CORRELATION_ID, CORRELATION_ID);
+    when(this.headers.getHeaders()).thenReturn(headersMap);
+
+    this.sut.publishMessage(SCHEMA_ID, EVENT_TYPE);
+
+    verify(this.driver, times(1)).publish(any(OqmMessage.class), any(), any());
+  }
+}
diff --git a/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmAuthorityStoreTest.java b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmAuthorityStoreTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6251e98990686cf95c84b43bbb1860c28eff3ae
--- /dev/null
+++ b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmAuthorityStoreTest.java
@@ -0,0 +1,219 @@
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import java.util.Optional;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.Kind;
+import org.opengroup.osdu.core.osm.core.model.Namespace;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.impl.OsmDestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.Authority;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class OsmAuthorityStoreTest {
+
+  private static final String COMMON_TENANT_ID = "common";
+  private static final String AUTHORITY_ID = "testAuthorityId";
+  private static final Destination DESTINATION = Destination.builder()
+      .partitionId("partitionId")
+      .namespace(new Namespace("namespace"))
+      .kind(new Kind("testKind"))
+      .build();
+
+  @InjectMocks
+  OsmAuthorityStore mockOsmAuthorityStore;
+
+  @Mock
+  Authority mockAuthority;
+
+  @Mock
+  DpsHeaders headers;
+
+  @Mock
+  ITenantFactory tenantFactory;
+
+  @Mock
+  TenantInfo tenantInfo;
+
+  @Mock
+  Context context;
+
+  @Mock
+  OsmDestinationProvider destinationProvider;
+
+  @Mock
+  JaxRsDpsLog log;
+
+  @Mock
+  PropertiesConfiguration configuration;
+
+
+  @Before
+  public void setUp() {
+    when(configuration.getSharedTenantName()).thenReturn(COMMON_TENANT_ID);
+    ReflectionTestUtils.setField(mockOsmAuthorityStore, "configuration", configuration);
+    when(headers.getPartitionId()).thenReturn("test");
+    when(tenantFactory.getTenantInfo("test")).thenReturn(tenantInfo);
+
+    when(mockAuthority.getAuthorityId()).thenReturn("os");
+
+    when(destinationProvider.getDestination(any(), any(), any())).thenReturn(DESTINATION);
+
+    when(context.getOne(any())).thenReturn(null);
+    when(context.findOne(any())).thenReturn(Optional.of(mockAuthority));
+    when(context.createAndGet(any(), any())).thenReturn(mockAuthority);
+  }
+
+  @Test
+  public void testGetAuthority() throws NotFoundException, ApplicationException {
+    assertNotNull(mockOsmAuthorityStore.get(AUTHORITY_ID));
+  }
+
+  @Test
+  public void testGetAuthority_SystemSchemas() throws NotFoundException, ApplicationException {
+    when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+    assertNotNull(mockOsmAuthorityStore.getSystemAuthority(AUTHORITY_ID));
+  }
+
+  @Test
+  public void testGetAuthority_NotFoundException() {
+    when(context.findOne(any())).thenReturn(Optional.empty());
+    try {
+      mockOsmAuthorityStore.get(Strings.EMPTY);
+      fail("Should not succeed");
+    } catch (NotFoundException e) {
+      assertEquals("bad input parameter", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testGetAuthority_NotFoundException_SystemSchemas() {
+    when(context.findOne(any())).thenReturn(Optional.empty());
+    try {
+      when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+      when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+      mockOsmAuthorityStore.get(Strings.EMPTY);
+      fail("Should not succeed");
+    } catch (NotFoundException e) {
+      assertEquals("bad input parameter", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreateAuthority()
+      throws NotFoundException, ApplicationException, BadRequestException {
+
+    assertNotNull(mockOsmAuthorityStore.create(mockAuthority));
+  }
+
+  @Test
+  public void testCreateAuthority_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+
+    when(mockAuthority.getAuthorityId()).thenReturn("os");
+    assertNotNull(mockOsmAuthorityStore.createSystemAuthority(mockAuthority));
+  }
+
+  @Test
+  public void testCreateAuthority_BadRequestException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    mockOsmAuthorityStore = Mockito.spy(mockOsmAuthorityStore);
+    when(context.getOne(any())).thenReturn(mockAuthority);
+    try {
+      mockOsmAuthorityStore.create(mockAuthority);
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("Authority already registered with Id: os", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreateAuthority_BadRequestException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    mockOsmAuthorityStore = Mockito.spy(mockOsmAuthorityStore);
+    when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+    when(context.getOne(any())).thenReturn(mockAuthority);
+    when(mockAuthority.getAuthorityId()).thenReturn("os");
+    try {
+      mockOsmAuthorityStore.createSystemAuthority(mockAuthority);
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("Authority already registered with Id: os", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreateAuthority_ApplicationException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    mockOsmAuthorityStore = Mockito.spy(mockOsmAuthorityStore);
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      mockOsmAuthorityStore.create(mockAuthority);
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(SchemaConstants.INVALID_INPUT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreateAuthority_ApplicationException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    mockOsmAuthorityStore = Mockito.spy(mockOsmAuthorityStore);
+    when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      mockOsmAuthorityStore.createSystemAuthority(mockAuthority);
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(SchemaConstants.INVALID_INPUT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+}
diff --git a/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmEntityTypeStoreTest.java b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmEntityTypeStoreTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3a5e0407966945b4fd9e4436380f2654243a4d7
--- /dev/null
+++ b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmEntityTypeStoreTest.java
@@ -0,0 +1,217 @@
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.opengroup.osdu.schema.constants.SchemaConstants.INVALID_INPUT;
+
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.Kind;
+import org.opengroup.osdu.core.osm.core.model.Namespace;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.destination.provider.impl.OsmDestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.EntityType;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class OsmEntityTypeStoreTest {
+
+  @InjectMocks
+  OsmEntityTypeStore osmEntityTypeStore;
+
+  @Mock
+  EntityType mockEntityType;
+
+  @Mock
+  DpsHeaders headers;
+
+  @Mock
+  OsmDestinationProvider destinationProvider;
+
+  @Mock
+  TenantInfo tenantInfo;
+
+  @Mock
+  Context context;
+
+  @Mock
+  JaxRsDpsLog log;
+
+  @Mock
+  PropertiesConfiguration configuration;
+
+  private static final String COMMON_TENANT_ID = "common";
+  private static final Destination DESTINATION = Destination.builder()
+      .partitionId("partitionId")
+      .namespace(new Namespace("namespace"))
+      .kind(new Kind("testKind"))
+      .build();
+
+  @Before
+  public void setUp() throws BadRequestException {
+    when(configuration.getSharedTenantName()).thenReturn(COMMON_TENANT_ID);
+    ReflectionTestUtils.setField(osmEntityTypeStore, "configuration", configuration);
+    when(headers.getPartitionId()).thenReturn("partitionId");
+    when(destinationProvider.getDestination(any(), any(), any())).thenReturn(DESTINATION);
+    when(context.getOne(any())).thenReturn(null);
+    when(context.createAndGet(any(), any())).thenReturn(mockEntityType);
+    when(context.findOne(any())).thenReturn(Optional.ofNullable(mockEntityType));
+  }
+
+  @Test
+  public void testGet() throws NotFoundException, ApplicationException {
+    System.out.println("testGet");
+    String entityId = "testEntityId";
+    assertNotNull(osmEntityTypeStore.get(entityId));
+  }
+
+  @Test
+  public void testGet_SystemSchemas() throws NotFoundException, ApplicationException {
+    System.out.println("testGet");
+    String entityId = "testEntityId";
+
+    assertNotNull(osmEntityTypeStore.getSystemEntity(entityId));
+  }
+
+  @Test
+  public void testGet_NotFoundException() {
+    System.out.println("testGet_NotFoundException");
+    String entityId = "";
+
+    when(context.findOne(any())).thenReturn(Optional.empty());
+
+    try {
+      osmEntityTypeStore.get(entityId);
+      fail("Should not succeed");
+    } catch (NotFoundException e) {
+      assertEquals("bad input parameter", e.getMessage());
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testGet_NotFoundException_SystemSchemas() {
+    System.out.println("testGet_NotFoundException");
+    String entityId = "";
+
+    when(context.findOne(any())).thenReturn(Optional.empty());
+
+    try {
+      osmEntityTypeStore.getSystemEntity(entityId);
+      fail("Should not succeed");
+    } catch (NotFoundException e) {
+      assertEquals("bad input parameter", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate() throws NotFoundException, ApplicationException, BadRequestException {
+    System.out.println("testCreate");
+    when(mockEntityType.getEntityTypeId()).thenReturn("wellbore");
+    assertNotNull(osmEntityTypeStore.create(mockEntityType));
+  }
+
+  @Test
+  public void testCreate_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    System.out.println("testCreate");
+    when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    when(mockEntityType.getEntityTypeId()).thenReturn("wellbore");
+
+    assertNotNull(osmEntityTypeStore.createSystemEntity(mockEntityType));
+  }
+
+  @Test
+  public void testCreate_BadRequestException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    System.out.println("testCreate_BadRequestException");
+
+    when(context.getOne(any())).thenReturn(mockEntityType);
+    when(mockEntityType.getEntityTypeId()).thenReturn("wks");
+
+    try {
+      osmEntityTypeStore.create(mockEntityType);
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("EntityType already registered with Id: wks", e.getMessage());
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate_BadRequestException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    System.out.println("testCreate_BadRequestException");
+
+    when(context.getOne(any())).thenReturn(mockEntityType);
+    when(mockEntityType.getEntityTypeId()).thenReturn("wks");
+
+    try {
+      osmEntityTypeStore.createSystemEntity(mockEntityType);
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("EntityType already registered with Id: wks", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate_ApplicationException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    System.out.println("testCreate_ApplicationException");
+
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+
+    try {
+      osmEntityTypeStore.create(mockEntityType);
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(INVALID_INPUT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate_ApplicationException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    System.out.println("testCreate_ApplicationException");
+
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+
+    try {
+      osmEntityTypeStore.createSystemEntity(mockEntityType);
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(INVALID_INPUT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+}
diff --git a/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSchemaInfoStoreTest.java b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSchemaInfoStoreTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..654e530b2cb5210674746a7dcf44ab08098c56b8
--- /dev/null
+++ b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSchemaInfoStoreTest.java
@@ -0,0 +1,605 @@
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.AppException;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.Kind;
+import org.opengroup.osdu.core.osm.core.model.Namespace;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorException;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.impl.OsmDestinationProvider;
+import org.opengroup.osdu.schema.enums.SchemaScope;
+import org.opengroup.osdu.schema.enums.SchemaStatus;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.QueryParams;
+import org.opengroup.osdu.schema.model.SchemaIdentity;
+import org.opengroup.osdu.schema.model.SchemaInfo;
+import org.opengroup.osdu.schema.model.SchemaRequest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class OsmSchemaInfoStoreTest {
+
+  private static final String COMMON_TENANT_ID = "common";
+  private static final Destination DESTINATION = Destination.builder()
+      .partitionId("partitionId")
+      .namespace(new Namespace("namespace"))
+      .kind(new Kind("testKind"))
+      .build();
+
+  @InjectMocks
+  OsmSchemaInfoStore schemaInfoStore;
+
+  @Mock
+  DpsHeaders headers;
+
+  @Mock
+  TenantInfo tenantInfo;
+
+  @Mock
+  TenantInfo tenantInfoCommon;
+
+  @Mock
+  List<Object> queryResult;
+
+  @Mock
+  ITenantFactory tenantFactory;
+
+  @Mock
+  JaxRsDpsLog log;
+
+  @Mock
+  Context context;
+
+  @Mock
+  OsmDestinationProvider destinationProvider;
+
+  @Mock
+  PropertiesConfiguration configuration;
+
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Before
+  public void setUp() {
+    when(configuration.getSharedTenantName()).thenReturn(COMMON_TENANT_ID);
+    ReflectionTestUtils.setField(schemaInfoStore, "configuration", configuration);
+    when(headers.getPartitionId()).thenReturn("tenant");
+    when(tenantFactory.getTenantInfo("tenant")).thenReturn(tenantInfo);
+
+    when(destinationProvider.getDestination(any(), any(), any())).thenReturn(DESTINATION);
+
+    when(context.getOne(any())).thenReturn(null);
+    when(context.findOne(any())).thenReturn(Optional.of(getMockSchemaObject_Published()));
+    when(context.createAndGet(any(), any())).thenReturn(getMockSchemaObject_Published());
+  }
+
+  @After
+  public void tearDown() {
+    queryResult.clear();
+  }
+
+  @Test
+  public void testGetLatestMinorVersion_ReturnNull()
+      throws NotFoundException, ApplicationException {
+    assertEquals("", schemaInfoStore.getLatestMinorVerSchema(getMockSchemaInfo()));
+  }
+
+  @Test
+  public void testGetSchemaInfo_NotEmptyEntity() throws NotFoundException, ApplicationException {
+    String schemaId = "schemaId";
+    this.setUpMocks("test", schemaId);
+    SchemaInfo schemaInfo = schemaInfoStore.getSchemaInfo(schemaId);
+    assertEquals(SchemaStatus.PUBLISHED, schemaInfo.getStatus());
+  }
+
+  @Test
+  public void testGetSchemaInfo_NotEmptyEntity_SystemSchemas()
+      throws NotFoundException, ApplicationException {
+    String schemaId = "schemaId";
+    this.setUpMocks(COMMON_TENANT_ID, schemaId);
+    SchemaInfo schemaInfo = schemaInfoStore.getSystemSchemaInfo(schemaId);
+    assertEquals(SchemaStatus.PUBLISHED, schemaInfo.getStatus());
+  }
+
+  @Test
+  public void testGetSchemaInfo_EmptyEntity() throws NotFoundException, ApplicationException {
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage(SchemaConstants.SCHEMA_NOT_PRESENT);
+    String schemaId = "schemaId";
+    this.setUpMocks("test", schemaId);
+    when(context.findOne(any())).thenReturn(Optional.empty());
+    schemaInfoStore.getSchemaInfo(schemaId);
+  }
+
+  @Test
+  public void testGetSchemaInfo_EmptyEntity_SystemSchemas()
+      throws NotFoundException, ApplicationException {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage(SchemaConstants.SCHEMA_NOT_PRESENT);
+
+    String schemaId = "schemaId";
+    this.setUpMocks(COMMON_TENANT_ID, schemaId);
+
+    when(context.findOne(any())).thenReturn(Optional.empty());
+
+    schemaInfoStore.getSystemSchemaInfo(schemaId);
+  }
+
+  @Test
+  public void testCreateSchemaInfo_Positive() throws ApplicationException, BadRequestException {
+    this.setUpMocks("test", "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("hmadhani@delfi.com");
+    assertNotNull(schemaInfoStore.createSchemaInfo(getMockSchemaObject_Published()));
+  }
+
+  @Test
+  public void testCreateSchemaInfo_Positive_SystemSchemas()
+      throws ApplicationException, BadRequestException {
+
+    this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("hmadhani@delfi.com");
+    assertNotNull(schemaInfoStore.createSystemSchemaInfo(getMockSchemaObject_Published()));
+  }
+
+  @Test
+  public void testIsUnique_True() throws ApplicationException {
+    String schemaId = "schemaId";
+    String tenantId = "tenant";
+    this.setUpMocksForMultiTenant_PositiveScenario(tenantId, COMMON_TENANT_ID, schemaId);
+    assertTrue(schemaInfoStore.isUnique(schemaId, tenantId));
+  }
+
+  @Test
+  public void testIsUnique_True_SystemSchemas() throws ApplicationException {
+    String schemaId = "schemaId";
+    String tenantId = "common";
+    this.setUpMocksForMultiTenant_PositiveScenario(tenantId, COMMON_TENANT_ID, schemaId);
+    assertTrue(schemaInfoStore.isUniqueSystemSchema(schemaId));
+  }
+
+  @Test
+  public void testIsUnique_False() throws ApplicationException {
+    String schemaId = "schemaId";
+    String tenantId = "tenant";
+    this.setUpMocksForMultiTenant_NegativeScenario(tenantId, COMMON_TENANT_ID, schemaId);
+    assertFalse(schemaInfoStore.isUnique(schemaId, tenantId));
+  }
+
+  @Test
+  public void testIsUnique_False_CommonTenant() throws ApplicationException {
+    String schemaId = "schemaId";
+    String tenantId = "common";
+    this.setUpMocksForMultiTenant_NegativeScenario(tenantId, COMMON_TENANT_ID, schemaId);
+    assertFalse(schemaInfoStore.isUnique(schemaId, tenantId));
+  }
+
+  @Test
+  public void testIsUnique_False_CommonTenant_SystemSchemas() throws ApplicationException {
+    String schemaId = "schemaId";
+    String tenantId = "common";
+    this.setUpMocksForMultiTenant_NegativeScenario(tenantId, COMMON_TENANT_ID, schemaId);
+    assertFalse(schemaInfoStore.isUniqueSystemSchema(schemaId));
+  }
+
+  @Test
+  public void testUpdateSchemaInfo()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    String tenantId = "test";
+    this.setUpMocks(tenantId, "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("hmadhani@delfi.com");
+    when(context.upsertAndGet(any(), any())).thenReturn(getMockSchemaObject_Published());
+    assertNotNull(schemaInfoStore.updateSchemaInfo(getMockSchemaObject_Published()));
+  }
+
+  @Test
+  public void testUpdateSchemaInfo_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("hmadhani@delfi.com");
+    when(context.upsertAndGet(any(), any())).thenReturn(getMockSchemaObject_Published());
+    assertNotNull(schemaInfoStore.updateSystemSchemaInfo(getMockSchemaObject_Published()));
+  }
+
+  @Test
+  public void testCreateSchemaInfo_WithSupersededBy()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks("test", "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("hmadhani@delfi.com");
+    when(context.findOne(any())).thenReturn(Optional.of(getMockSchemaObject_SuperSededObject()));
+    assertNotNull(schemaInfoStore.createSchemaInfo(getMockSchemaObject_SuperSededBy()));
+  }
+
+  @Test
+  public void testCreateSchemaInfo_WithSupersededBy_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("hmadhani@delfi.com");
+    when(context.findOne(any())).thenReturn(Optional.of(getMockSchemaObject_SuperSededObject()));
+    assertNotNull(schemaInfoStore.createSystemSchemaInfo(getMockSchemaObject_SuperSededBy()));
+  }
+
+  @Test
+  public void testUpdateSchemaInfo_SupersededByException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    when(context.findOne(any())).thenReturn(Optional.empty());
+    try {
+      this.setUpMocks("test", "os:wks:well.1.1.1");
+      schemaInfoStore.updateSchemaInfo(getMockSchemaObject_SuperSededBy());
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("Invalid SuperSededBy id", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testUpdateSchemaInfo_SupersededByException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    when(context.findOne(any())).thenReturn(Optional.empty());
+    try {
+      this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+      schemaInfoStore.updateSystemSchemaInfo(getMockSchemaObject_SuperSededBy());
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("Invalid SuperSededBy id", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testUpdateInfo_SupersededByWithoutIdException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks("test", "os:wks:well.1.1.1");
+    SchemaRequest schemaRequest = getMockSchemaObject_SuperSededByWithoutId();
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage(SchemaConstants.INVALID_SUPERSEDEDBY_ID);
+
+    when(context.getOne(any())).thenReturn(null);
+
+    schemaInfoStore.updateSchemaInfo(schemaRequest);
+  }
+
+  @Test
+  public void testUpdateInfo_SupersededByWithoutIdException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+    SchemaRequest schemaRequest = getMockSchemaObject_SuperSededByWithoutId();
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage(SchemaConstants.INVALID_SUPERSEDEDBY_ID);
+    schemaInfoStore.updateSystemSchemaInfo(schemaRequest);
+  }
+
+  @Test
+  public void testCreateSchemaInfo_BadRequestException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+
+    this.setUpMocks("test", "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("dummy-user");
+    when(context.getOne(any())).thenReturn(getMockSchemaObject_Published());
+    try {
+      schemaInfoStore.createSchemaInfo(getMockSchemaObject_Published());
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals(SchemaConstants.SCHEMA_ID_EXISTS, e.getMessage());
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreateSchemaInfo_BadRequestException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+
+    this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("dummy-user");
+    when(context.getOne(any())).thenReturn(getMockSchemaObject_Published());
+    try {
+      schemaInfoStore.createSystemSchemaInfo(getMockSchemaObject_Published());
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals(SchemaConstants.SCHEMA_ID_EXISTS, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreateSchemaInfo_ApplicationException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks("test", "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("dummy-user");
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      schemaInfoStore.createSchemaInfo(getMockSchemaObject_Published());
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(SchemaConstants.SCHEMA_CREATION_FAILED_INVALID_OBJECT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreateSchemaInfo_ApplicationException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("dummy-user");
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      schemaInfoStore.createSystemSchemaInfo(getMockSchemaObject_Published());
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(SchemaConstants.SCHEMA_CREATION_FAILED_INVALID_OBJECT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testUpdateSchemaInfo_ApplicationException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks("test", "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("dummy-user");
+    when(context.upsertAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      schemaInfoStore.updateSchemaInfo(getMockSchemaObject_Published());
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals("Invalid object, update failed", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testUpdateSchemaInfo_ApplicationException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    this.setUpMocks(COMMON_TENANT_ID, "os:wks:well.1.1.1");
+    when(headers.getUserEmail()).thenReturn("dummy-user");
+    when(context.upsertAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      schemaInfoStore.updateSystemSchemaInfo(getMockSchemaObject_Published());
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals("Invalid object, update failed", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testGetLatestMinorVersion_Entity() throws NotFoundException, ApplicationException {
+    when(headers.getPartitionId()).thenReturn("test");
+    when(tenantFactory.getTenantInfo("test")).thenReturn(tenantInfo);
+    when(headers.getUserEmail()).thenReturn("hmadhani@delfi.com");
+    when(context.getResultsAsList(any())).thenReturn(
+        Collections.singletonList(getMockSchemaObject_Published()));
+    assertEquals("{}", schemaInfoStore.getLatestMinorVerSchema(getMockSchemaInfo()));
+  }
+
+  @Test
+  public void testGetSchemaInfoList_withoutqueryparam()
+      throws NotFoundException, ApplicationException, BadRequestException {
+
+    when(headers.getPartitionId()).thenReturn("test");
+    when(tenantFactory.getTenantInfo("test")).thenReturn(tenantInfo);
+    when(tenantInfo.getName()).thenReturn("test");
+    when(context.getResultsAsList(any())).thenReturn(
+        Collections.singletonList(getMockSchemaObject_Published()));
+    assertEquals(1,
+        schemaInfoStore.getSchemaInfoList(QueryParams.builder().limit(100).offset(0).build(),
+            "test").size());
+  }
+
+  @Test
+  public void testGetSchemaInfoList_withoutqueryparam_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+
+    when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+    when(tenantInfo.getName()).thenReturn(COMMON_TENANT_ID);
+    when(context.getResultsAsList(any())).thenReturn(
+        Collections.singletonList(getMockSchemaObject_Published()));
+    assertEquals(1,
+        schemaInfoStore.getSystemSchemaInfoList(QueryParams.builder().limit(100).offset(0).build())
+            .size());
+  }
+
+  @Test
+  public void testGetSchemaInfoList_withqueryparam()
+      throws NotFoundException, ApplicationException, BadRequestException {
+
+    when(headers.getPartitionId()).thenReturn("test");
+    when(tenantFactory.getTenantInfo("test")).thenReturn(tenantInfo);
+    when(tenantInfo.getName()).thenReturn("test");
+    when(context.getResultsAsList(any())).thenReturn(
+        Collections.singletonList(getMockSchemaObject_Published()));
+    assertEquals(1,
+        schemaInfoStore.getSchemaInfoList(QueryParams.builder().authority("test").source("test")
+            .entityType("test").schemaVersionMajor(1l).schemaVersionMinor(1l).scope("test")
+            .status("test")
+            .latestVersion(false).limit(100).offset(0).build(), "test").size());
+  }
+
+  @Test
+  public void testCleanSchema_Success() throws ApplicationException {
+    String schemaId = "schemaId";
+    String dataPartitionId = "tenant1";
+    this.setUpMocks(dataPartitionId, schemaId);
+    assertEquals(true, schemaInfoStore.cleanSchema(schemaId));
+  }
+
+  @Test
+  public void testCleanSchema_Success_SystemSchemas() throws ApplicationException {
+    String schemaId = "schemaId";
+    this.setUpMocks(COMMON_TENANT_ID, schemaId);
+    assertEquals(true, schemaInfoStore.cleanSchema(schemaId));
+  }
+
+  @Test
+  public void testCleanSchema_Failure() throws ApplicationException, TranslatorException {
+    String schemaId = "schemaId";
+    String dataPartitionId = "tenant1";
+    this.setUpMocks(dataPartitionId, schemaId);
+    doThrow(TranslatorException.class).when(context).delete(any(), any(), any());
+    assertEquals(false, schemaInfoStore.cleanSchema(schemaId));
+  }
+
+  @Test
+  public void testCleanSchema_Failure_SystemSchemas()
+      throws ApplicationException, TranslatorException {
+    String schemaId = "schemaId";
+    this.setUpMocks(COMMON_TENANT_ID, schemaId);
+    doThrow(TranslatorException.class).when(context).delete(any(), any(), any());
+    assertEquals(false, schemaInfoStore.cleanSchema(schemaId));
+  }
+
+  @Test
+  public void testMisconfiguredTenantInfoShouldThrowException() throws ApplicationException {
+    String schemaId = "schemaId";
+    String tenantId = "common";
+    this.setUpMocks(tenantId, schemaId);
+    when(context.getResultsAsList(any())).thenThrow(TranslatorRuntimeException.class);
+    expectedException.expect(AppException.class);
+    expectedException.expectMessage(
+        "Misconfigured tenant-info for common, not possible to check schema uniqueness");
+    schemaInfoStore.isUnique(schemaId, tenantId);
+  }
+
+  private SchemaRequest getMockSchemaObject_Published() {
+    return SchemaRequest.builder().schema("{}")
+        .schemaInfo(SchemaInfo.builder()
+            .schemaIdentity(
+                SchemaIdentity.builder().authority("os").source("wks").entityType("well")
+                    .schemaVersionMajor(1L).schemaVersionMinor(1L).schemaVersionPatch(1L)
+                    .id("os:wks:well.1.1.1").build())
+            .scope(SchemaScope.SHARED).status(SchemaStatus.PUBLISHED).createdBy("subham").build())
+        .build();
+
+  }
+
+  private SchemaInfo getMockSchemaInfo() {
+    return SchemaInfo.builder()
+        .schemaIdentity(
+            SchemaIdentity.builder().authority("os").source("wks").entityType("well")
+                .schemaVersionMajor(1L)
+                .schemaVersionMinor(1L).schemaVersionPatch(1L).id("os:wks:well.1.1.1").build())
+        .scope(SchemaScope.SHARED).status(SchemaStatus.PUBLISHED).createdBy("subham")
+
+        .build();
+
+  }
+
+  private SchemaRequest getMockSchemaObject_SuperSededBy() {
+    return SchemaRequest.builder().schema("{}")
+        .schemaInfo(SchemaInfo.builder()
+            .schemaIdentity(
+                SchemaIdentity.builder().authority("os").source("wks").entityType("well")
+                    .schemaVersionMajor(1L).schemaVersionMinor(1L).schemaVersionPatch(1L)
+                    .id("os:wks:well.1.1.1").build())
+            .scope(SchemaScope.SHARED).status(SchemaStatus.PUBLISHED).createdBy("subham")
+            .supersededBy(SchemaIdentity.builder().authority("os").source("wks").entityType("well")
+                .schemaVersionMajor(1L).schemaVersionMinor(2L).schemaVersionPatch(1L)
+                .id("os:wks:well.1.2.1").build())
+            .build())
+        .build();
+
+  }
+
+  private SchemaRequest getMockSchemaObject_SuperSededObject() {
+    return SchemaRequest.builder().schema("{}")
+        .schemaInfo(SchemaInfo.builder()
+            .schemaIdentity(
+                SchemaIdentity.builder().authority("os").source("wks").entityType("well")
+                    .schemaVersionMajor(1L).schemaVersionMinor(2L).schemaVersionPatch(1L)
+                    .id("os:wks:well.1.2.1").build())
+            .scope(SchemaScope.SHARED).status(SchemaStatus.PUBLISHED).createdBy("subham")
+            .build())
+        .build();
+
+  }
+
+  private SchemaRequest getMockSchemaObject_SuperSededByWithoutId() {
+    return SchemaRequest.builder().schema("{}")
+        .schemaInfo(SchemaInfo.builder()
+            .schemaIdentity(
+                SchemaIdentity.builder().authority("os").source("wks").entityType("well")
+                    .schemaVersionMajor(1L).schemaVersionMinor(1L).schemaVersionPatch(1L)
+                    .id("os:wks:well.1.1.1").build())
+            .scope(SchemaScope.SHARED).status(SchemaStatus.DEVELOPMENT).createdBy("subham")
+            .supersededBy(SchemaIdentity.builder().authority("os").source("wks").entityType("well")
+                .schemaVersionMajor(1L).schemaVersionMinor(1L).schemaVersionPatch(1L).build())
+            .build())
+        .build();
+
+  }
+
+  private void setUpMocks(String dataPartitionId, String schemaId) {
+    when(headers.getPartitionId()).thenReturn(dataPartitionId);
+    when(tenantFactory.getTenantInfo(dataPartitionId)).thenReturn(tenantInfo);
+  }
+
+  private void setUpMocksForMultiTenant_PositiveScenario(String privateTenant, String commonTenant,
+      String schemaId) {
+    this.setUpMocksForMultipleTenants(privateTenant, commonTenant, schemaId);
+    when(context.getResultsAsList(any())).thenReturn(queryResult);
+    when(queryResult.isEmpty()).thenReturn(true);
+  }
+
+  private void setUpMocksForMultiTenant_NegativeScenario(String privateTenant, String commonTenant,
+      String schemaId) {
+    this.setUpMocksForMultipleTenants(privateTenant, commonTenant, schemaId);
+    when(context.getResultsAsList(any())).thenReturn(queryResult);
+    when(queryResult.size()).thenReturn(2);
+  }
+
+  private void setUpMocksForMultipleTenants(String privateTenant, String commonTenant,
+      String schemaId) {
+    when(configuration.getSharedTenantName()).thenReturn(commonTenant);
+    when(tenantFactory.getTenantInfo(privateTenant)).thenReturn(tenantInfo);
+    when(tenantFactory.getTenantInfo(commonTenant)).thenReturn(tenantInfoCommon);
+    when(tenantInfo.getName()).thenReturn(privateTenant);
+    when(tenantInfoCommon.getName()).thenReturn(commonTenant);
+  }
+}
diff --git a/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSourceStoreTest.java b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSourceStoreTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c5d23f49b37a5ea1a7afaae60cbd11fc4ea4efc
--- /dev/null
+++ b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemainfostore/OsmSourceStoreTest.java
@@ -0,0 +1,214 @@
+package org.opengroup.osdu.schema.impl.schemainfostore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import java.util.Optional;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.osm.core.model.Destination;
+import org.opengroup.osdu.core.osm.core.model.Kind;
+import org.opengroup.osdu.core.osm.core.model.Namespace;
+import org.opengroup.osdu.core.osm.core.service.Context;
+import org.opengroup.osdu.core.osm.core.translate.TranslatorRuntimeException;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.impl.OsmDestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.BadRequestException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.opengroup.osdu.schema.model.Source;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class OsmSourceStoreTest {
+
+  private static final String SOURCE_ID = "sourceId";
+  private static final String COMMON_TENANT_ID = "common";
+  private static final Destination DESTINATION = Destination.builder()
+      .partitionId("partitionId")
+      .namespace(new Namespace("namespace"))
+      .kind(new Kind("testKind"))
+      .build();
+
+  @InjectMocks
+  OsmSourceStore osmSourceStore;
+
+  @Mock
+  Source mockSource;
+
+  @Mock
+  DpsHeaders headers;
+
+  @Mock
+  TenantInfo tenantInfo;
+
+  @Mock
+  ITenantFactory tenantFactory;
+
+  @Mock
+  JaxRsDpsLog log;
+
+  @Mock
+  Context context;
+
+  @Mock
+  OsmDestinationProvider destinationProvider;
+
+  @Mock
+  PropertiesConfiguration configuration;
+
+  @Before
+  public void setUp() {
+    when(configuration.getSharedTenantName()).thenReturn(COMMON_TENANT_ID);
+    ReflectionTestUtils.setField(osmSourceStore, "configuration", configuration);
+    Mockito.when(headers.getPartitionId()).thenReturn("test");
+    Mockito.when(tenantFactory.getTenantInfo("test")).thenReturn(tenantInfo);
+
+    Mockito.when(mockSource.getSourceId()).thenReturn("wks");
+
+    when(destinationProvider.getDestination(any(), any(), any())).thenReturn(DESTINATION);
+
+    when(context.getOne(any())).thenReturn(null);
+    when(context.findOne(any())).thenReturn(Optional.of(mockSource));
+    when(context.createAndGet(any(), any())).thenReturn(mockSource);
+  }
+
+  @Test
+  public void testGet() throws NotFoundException, ApplicationException {
+    assertNotNull(osmSourceStore.get(SOURCE_ID));
+  }
+
+  @Test
+  public void testGet_SystemSchemas() throws NotFoundException, ApplicationException {
+    Mockito.when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    Mockito.when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+
+    assertNotNull(osmSourceStore.getSystemSource(SOURCE_ID));
+  }
+
+  @Test
+  public void testGet_NotFoundException() {
+    when(context.findOne(any())).thenReturn(Optional.empty());
+    try {
+      osmSourceStore.get(Strings.EMPTY);
+      fail("Should not succeed");
+    } catch (NotFoundException e) {
+      assertEquals("bad input parameter", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testGet_NotFoundException_SystemSchemas() {
+    when(context.findOne(any())).thenReturn(Optional.empty());
+    try {
+      when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+      when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+      osmSourceStore.getSystemSource(Strings.EMPTY);
+      fail("Should not succeed");
+    } catch (NotFoundException e) {
+      assertEquals("bad input parameter", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate() throws NotFoundException, ApplicationException, BadRequestException {
+    assertNotNull(osmSourceStore.create(mockSource));
+  }
+
+  @Test
+  public void testCreate_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    Mockito.when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    Mockito.when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+
+    assertNotNull(osmSourceStore.createSystemSource(mockSource));
+  }
+
+  @Test
+  public void testCreate_BadRequestException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    osmSourceStore = Mockito.spy(osmSourceStore);
+    when(context.getOne(any())).thenReturn(mockSource);
+    try {
+      osmSourceStore.create(mockSource);
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("Source already registered with Id: wks", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate_BadRequestException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    osmSourceStore = Mockito.spy(osmSourceStore);
+    Mockito.when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    Mockito.when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+    when(context.getOne(any())).thenReturn(mockSource);
+    try {
+      osmSourceStore.createSystemSource(mockSource);
+      fail("Should not succeed");
+    } catch (BadRequestException e) {
+      assertEquals("Source already registered with Id: wks", e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate_ApplicationException()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    osmSourceStore = Mockito.spy(osmSourceStore);
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      osmSourceStore.create(mockSource);
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(SchemaConstants.INVALID_INPUT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+
+  @Test
+  public void testCreate_ApplicationException_SystemSchemas()
+      throws NotFoundException, ApplicationException, BadRequestException {
+    osmSourceStore = Mockito.spy(osmSourceStore);
+    Mockito.when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+    Mockito.when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(tenantInfo);
+    when(context.createAndGet(any(), any())).thenThrow(TranslatorRuntimeException.class);
+    try {
+      osmSourceStore.createSystemSource(mockSource);
+      fail("Should not succeed");
+    } catch (ApplicationException e) {
+      assertEquals(SchemaConstants.INVALID_INPUT, e.getMessage());
+
+    } catch (Exception e) {
+      fail("Should not get different exception");
+    }
+  }
+}
diff --git a/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemastore/ObmSchemaStoreTest.java b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemastore/ObmSchemaStoreTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c719a6cd12752be547ab81def51bc88ca82e1d7
--- /dev/null
+++ b/schema-core-plus/src/test/java/org/opengroup/osdu/schema/impl/schemastore/ObmSchemaStoreTest.java
@@ -0,0 +1,217 @@
+package org.opengroup.osdu.schema.impl.schemastore;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
+import org.opengroup.osdu.core.common.model.http.DpsHeaders;
+import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
+import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver;
+import org.opengroup.osdu.core.common.provider.interfaces.ITenantFactory;
+import org.opengroup.osdu.core.obm.core.Driver;
+import org.opengroup.osdu.core.obm.core.ObmDriverRuntimeException;
+import org.opengroup.osdu.core.obm.core.model.Blob;
+import org.opengroup.osdu.core.obm.core.persistence.ObmDestination;
+import org.opengroup.osdu.schema.configuration.PartitionPropertyNames;
+import org.opengroup.osdu.schema.configuration.PropertiesConfiguration;
+import org.opengroup.osdu.schema.constants.SchemaConstants;
+import org.opengroup.osdu.schema.destination.provider.impl.ObmDestinationProvider;
+import org.opengroup.osdu.schema.exceptions.ApplicationException;
+import org.opengroup.osdu.schema.exceptions.NotFoundException;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class ObmSchemaStoreTest {
+
+    private static final ObmDestination DESTINATION = ObmDestination.builder().partitionId("partitionId").build();
+    @InjectMocks
+    ObmSchemaStore schemaStore;
+
+    @Mock
+    private Driver driver;
+    @Mock
+    private Blob blob;
+    @Mock
+    private ObmDestinationProvider destinationProvider;
+    @Mock
+    DpsHeaders headers;
+    @Mock
+    ITenantFactory tenantFactory;
+    @Mock
+    TenantInfo TenantInfo;
+    @Mock
+    JaxRsDpsLog log;
+    @Mock
+    PropertiesConfiguration configuration;
+    @Mock
+    PartitionPropertyNames partitionPropertyNames;
+    @Mock
+    PartitionPropertyResolver partitionPropertyResolver;
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    private static final String BUCKET = "test-schema";
+    private static final String dataPartitionId = "dataPartitionId";
+    private static final String FILE_PATH = "/test-folder/test-file";
+    private static final String CONTENT = "Hello World";
+    private static final String COMMON_TENANT_ID = "common";
+    private static final String COMMON_TENANT_BUCKET = "common-schema";
+
+    @Before
+    public void setUp() {
+        when(configuration.getSharedTenantName()).thenReturn(COMMON_TENANT_ID);
+    	 ReflectionTestUtils.setField(schemaStore, "configuration", configuration);
+
+         when(destinationProvider.getDestination(any())).thenReturn(DESTINATION);
+         when(driver.createAndGetBlob(any(), any(), any())).thenReturn(blob);
+    }
+
+    @Test
+    public void testCreateSchema() throws ApplicationException {
+
+        when(headers.getPartitionId()).thenReturn(dataPartitionId);
+        String filepath = FILE_PATH + SchemaConstants.JSON_EXTENSION;
+        when(tenantFactory.getTenantInfo(dataPartitionId)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn("test");
+        when(blob.getName()).thenReturn(BUCKET + filepath);
+        when(driver.createAndGetBlob(any(), any(), any())). thenReturn(blob);
+
+        String blobName = schemaStore.createSchema(FILE_PATH, CONTENT);
+
+        Assert.assertEquals((BUCKET + filepath), blobName);
+    }
+
+    @Test
+    public void testCreateSchema_SystemSchemas() throws ApplicationException {
+
+        when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+        String filepath = FILE_PATH + SchemaConstants.JSON_EXTENSION;
+        when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn(COMMON_TENANT_ID);
+        when(blob.getName()).thenReturn(COMMON_TENANT_BUCKET + filepath);
+        when(driver.createAndGetBlob(any(), any(), any())).thenReturn(blob);
+
+        String blobName = schemaStore.createSystemSchema(FILE_PATH, CONTENT);
+
+        Assert.assertEquals((COMMON_TENANT_BUCKET + filepath), blobName);
+    }
+
+    @Test
+    public void testCreateSchema_Failure() throws ApplicationException {
+        expectedException.expect(ApplicationException.class);
+        expectedException.expectMessage(SchemaConstants.INTERNAL_SERVER_ERROR);
+
+        when(headers.getPartitionId()).thenReturn(dataPartitionId);
+        String filepath = FILE_PATH + SchemaConstants.JSON_EXTENSION;
+        when(tenantFactory.getTenantInfo(dataPartitionId)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn("test");
+        when(driver.createAndGetBlob(any(), any(), any())).thenThrow(ObmDriverRuntimeException.class);
+
+        schemaStore.createSchema(FILE_PATH, CONTENT);
+    }
+
+    @Test
+    public void testCreateSchema_Failure_SystemSchemas() throws ApplicationException {
+        expectedException.expect(ApplicationException.class);
+        expectedException.expectMessage(SchemaConstants.INTERNAL_SERVER_ERROR);
+
+        when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+        String filepath = FILE_PATH + SchemaConstants.JSON_EXTENSION;
+        when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn(COMMON_TENANT_ID);
+        when(driver.createAndGetBlob(any(), any(), any())).thenThrow(ObmDriverRuntimeException.class);
+
+        schemaStore.createSystemSchema(FILE_PATH, CONTENT);
+    }
+
+    @Test
+    public void testGetSchema() throws ApplicationException, NotFoundException {
+        when(tenantFactory.getTenantInfo(dataPartitionId)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn("test");
+        when(driver.getBlobContent(any(), any(), any())).thenReturn(CONTENT.getBytes());
+        Assert.assertEquals(CONTENT, schemaStore.getSchema(dataPartitionId, FILE_PATH));
+    }
+
+    @Test
+    public void testGetSchema_SystemSchemas() throws ApplicationException, NotFoundException {
+        when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn(COMMON_TENANT_ID);
+        when(driver.getBlobContent(any(), any(), any())).thenReturn(CONTENT.getBytes());
+        Assert.assertEquals(CONTENT, schemaStore.getSystemSchema(FILE_PATH));
+    }
+
+    @Test
+    public void testGetSchema_NotFound() throws ApplicationException, NotFoundException {
+
+        expectedException.expect(NotFoundException.class);
+        expectedException.expectMessage(SchemaConstants.SCHEMA_NOT_PRESENT);
+        String filePath = FILE_PATH + SchemaConstants.JSON_EXTENSION;
+        when(tenantFactory.getTenantInfo(dataPartitionId)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn("test");
+        when(driver.getBlobContent(BUCKET, filePath, DESTINATION)).thenReturn(null);
+        schemaStore.getSchema(dataPartitionId, FILE_PATH);
+    }
+
+    @Test
+    public void testGetSchema_NotFound_StorageException() throws ApplicationException, NotFoundException {
+
+        expectedException.expect(NotFoundException.class);
+        expectedException.expectMessage(SchemaConstants.SCHEMA_NOT_PRESENT);
+        String filePath = FILE_PATH + SchemaConstants.JSON_EXTENSION;
+        ObmDriverRuntimeException obmDriverRuntimeException = new ObmDriverRuntimeException(404, new RuntimeException());
+
+        when(tenantFactory.getTenantInfo(dataPartitionId)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn("test");
+        when(driver.getBlobContent(BUCKET, filePath, DESTINATION)).thenThrow(obmDriverRuntimeException);
+        schemaStore.getSchema(dataPartitionId, FILE_PATH);
+    }
+
+    @Test
+    public void testGetSchema_NotFound_SystemSchemas() throws ApplicationException, NotFoundException {
+        expectedException.expect(NotFoundException.class);
+        expectedException.expectMessage(SchemaConstants.SCHEMA_NOT_PRESENT);
+
+        when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn(COMMON_TENANT_ID);
+        when(driver.getBlobContent(any(), any(), any())).thenReturn(null);
+        schemaStore.getSystemSchema(FILE_PATH);
+    }
+
+    @Test
+    public void testDeleteSchema() throws ApplicationException {
+
+        when(headers.getPartitionId()).thenReturn(dataPartitionId);
+        String filepath = FILE_PATH + SchemaConstants.JSON_EXTENSION;
+        when(tenantFactory.getTenantInfo(dataPartitionId)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn("test");
+        when(driver.deleteBlob(any(), any(), any())).thenReturn(true);
+
+        Boolean result = schemaStore.cleanSchemaProject(FILE_PATH);
+
+        Assert.assertEquals(true, result);
+    }
+
+    @Test
+    public void testDeleteSchema_SystemSchemas() throws ApplicationException {
+
+        when(headers.getPartitionId()).thenReturn(COMMON_TENANT_ID);
+        when(tenantFactory.getTenantInfo(COMMON_TENANT_ID)).thenReturn(TenantInfo);
+        when(TenantInfo.getProjectId()).thenReturn(COMMON_TENANT_ID);
+        when(driver.deleteBlob(any(), any(), any())).thenReturn(true);
+
+        Boolean result = schemaStore.cleanSystemSchemaProject(FILE_PATH);
+
+        Assert.assertEquals(true, result);
+    }
+
+}
diff --git a/schema-core-plus/src/test/resources/application.properties b/schema-core-plus/src/test/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/schema-core-plus/src/test/resources/logback-test.xml b/schema-core-plus/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cb0f072e1bd3bf7b4e1825d5a37d3feb927de7ce
--- /dev/null
+++ b/schema-core-plus/src/test/resources/logback-test.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <include resource="org/springframework/boot/logging/logback/base.xml" />
+    <logger name="org.springframework" level="WARN"/>
+</configuration>
diff --git a/schema-core-plus/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/schema-core-plus/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000000000000000000000000000000000..ca6ee9cea8ec189a088d50559325d4e84ff8ad09
--- /dev/null
+++ b/schema-core-plus/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
\ No newline at end of file