You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by ra...@apache.org on 2023/11/22 11:27:52 UTC

(incubator-kie-tools-temporary-rnd-do-not-use) 01/01: KOGITO-9195: YaRD editor validation (#1696)

This is an automated email from the ASF dual-hosted git repository.

rantunes pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools-temporary-rnd-do-not-use.git

commit 687c32adc4e099f9724d45259bc0c2a40d63d91e
Author: Toni Rikkola <to...@rikkola.net>
AuthorDate: Tue Nov 21 18:54:49 2023 +0000

    KOGITO-9195: YaRD editor validation (#1696)
---
 packages/serverless-logic-web-tools/package.json   |   1 +
 .../src/editor/EditorPage.tsx                      |   8 +-
 .../src/editor/EditorToolbar.tsx                   |  28 +-
 .../src/editor/hooks/useEditorNotifications.tsx    |  14 +-
 .../serverless-logic-web-tools/webpack.config.ts   |   4 +
 packages/yard-editor/dev-webapp/webpack.config.js  |   4 +
 packages/yard-editor/package.json                  |   1 +
 packages/yard-editor/src/editor/YardEditorView.tsx |  21 +-
 packages/yard-model/LICENSE                        | 201 +++++++++++++
 packages/yard-model/env/index.js                   |  31 ++
 packages/yard-model/install.js                     |  25 ++
 packages/yard-model/package.json                   |  48 +++
 packages/yard-model/pom.xml                        |  97 +++++++
 .../main/java/org/yard/model/DecisionLogic.java    |  32 ++
 .../main/java/org/yard/model/DecisionTable.java    |  72 +++++
 .../src/main/java/org/yard/model/Element.java      |  65 +++++
 .../src/main/java/org/yard/model/InlineRule.java   |  45 +++
 .../src/main/java/org/yard/model/Input.java        |  44 +++
 .../java/org/yard/model/LiteralExpression.java     |  35 +++
 .../src/main/java/org/yard/model/Operators.java    |  49 ++++
 .../src/main/java/org/yard/model/Rule.java         |  23 ++
 .../java/org/yard/model/RuleDefSerializer.java     |  88 ++++++
 .../src/main/java/org/yard/model/WhenThenRule.java |  53 ++++
 .../org/yard/model/WhenThenRuleThenSerializer.java |  56 ++++
 .../src/main/java/org/yard/model/YaRD.java         |  83 ++++++
 packages/yard-validator-worker/README.md           |  22 ++
 packages/yard-validator-worker/demo/demo.html      |  72 +++++
 packages/yard-validator-worker/env/index.js        |  31 ++
 packages/yard-validator-worker/install.js          |  25 ++
 packages/yard-validator-worker/package.json        |  50 ++++
 packages/yard-validator-worker/pom.xml             | 105 +++++++
 .../java/org/yard/validator/CustomTreeSet.java     | 121 ++++++++
 .../src/main/java/org/yard/validator/Issue.java    |  49 ++++
 .../src/main/java/org/yard/validator/Parser.java   | 236 +++++++++++++++
 .../main/java/org/yard/validator/ParserResult.java |  46 +++
 .../main/java/org/yard/validator/ReportBus.java    |  23 ++
 .../java/org/yard/validator/YardValidator.java     |  97 +++++++
 .../src/main/java/org/yard/validator/app.js        |  34 +++
 .../main/java/org/yard/validator/checks/Check.java |  27 ++
 .../java/org/yard/validator/checks/CheckItem.java  |  57 ++++
 .../org/yard/validator/checks/CheckProducer.java   | 136 +++++++++
 .../java/org/yard/validator/checks/RunBundle.java  |  39 +++
 .../yard/validator/checks/SubsumptionCheck.java    | 265 +++++++++++++++++
 .../java/org/yard/validator/key/ColumnKey.java     |  58 ++++
 .../src/main/java/org/yard/validator/key/Key.java  |  29 ++
 .../main/java/org/yard/validator/key/KeyImpl.java  |  46 +++
 .../java/org/yard/validator/key/KeyParent.java     |  28 ++
 .../main/java/org/yard/validator/key/Location.java |  27 ++
 .../java/org/yard/validator/key/ObjectKey.java     |  40 +++
 .../org/yard/validator/key/OperatorValueKey.java   |  50 ++++
 .../java/org/yard/validator/key/RowLocation.java   |  49 ++++
 .../java/org/yard/validator/runner/Runner.java     |  48 +++
 .../java/org/yard/validator/util/Callback.java     |  26 ++
 .../main/java/org/yard/validator/util/Date.java    |  72 +++++
 .../main/java/org/yard/validator/util/Logger.java  |  41 +++
 .../test/java/org/yard/validator/ParserTest.java   |  84 ++++++
 .../java/org/yard/validator/YardValidatorTest.java | 161 ++++++++++
 .../java/org/yard/validator/util/DateTest.java     |  66 +++++
 .../resources/org/yard/validator/redundancy.yml    |  26 ++
 .../resources/org/yard/validator/service-price.yml |  24 ++
 .../yard/validator/subsumption-the-other-way.yml   |  29 ++
 .../resources/org/yard/validator/subsumption.yml   |  29 ++
 .../yard/validator/traffic-violation-empty-row.yml |  29 ++
 .../org/yard/validator/traffic-violation.yml       |  28 ++
 packages/yard-validator/README.md                  |   8 +
 packages/yard-validator/env/index.js               |  31 ++
 packages/yard-validator/install.js                 |  25 ++
 packages/yard-validator/package.json               |  44 +++
 packages/yard-validator/src/ValidationResult.ts    |  32 ++
 packages/yard-validator/src/index.ts               |  20 ++
 packages/yard-validator/src/main.ts                |  55 ++++
 packages/yard-validator/tsconfig.json              |   9 +
 pnpm-lock.yaml                                     | 323 +++++++++------------
 repo/graph.dot                                     |   8 +
 repo/graph.json                                    |  11 +
 75 files changed, 3923 insertions(+), 196 deletions(-)

diff --git a/packages/serverless-logic-web-tools/package.json b/packages/serverless-logic-web-tools/package.json
index 33748eba73..e81da92dcd 100644
--- a/packages/serverless-logic-web-tools/package.json
+++ b/packages/serverless-logic-web-tools/package.json
@@ -54,6 +54,7 @@
     "@kie-tools/text-editor": "workspace:*",
     "@kie-tools/yard-editor": "workspace:*",
     "@kie-tools/yard-language-service": "workspace:*",
+    "@kie-tools/yard-validator": "workspace:*",
     "@octokit/plugin-rest-endpoint-methods": "^5.0.1",
     "@octokit/rest": "^18.5.3",
     "@patternfly/patternfly": "^4.224.2",
diff --git a/packages/serverless-logic-web-tools/src/editor/EditorPage.tsx b/packages/serverless-logic-web-tools/src/editor/EditorPage.tsx
index b1164c9400..f259600546 100644
--- a/packages/serverless-logic-web-tools/src/editor/EditorPage.tsx
+++ b/packages/serverless-logic-web-tools/src/editor/EditorPage.tsx
@@ -71,7 +71,7 @@ export function EditorPage(props: Props) {
   const queryParams = useQueryParams();
   const alertsDispatch = useGlobalAlertsDispatchContext();
 
-  const notifications = useEditorNotifications({
+  const { notifications, onLazyValidate } = useEditorNotifications({
     webToolsEditor,
     content: lastContent.current,
     fileRelativePath: props.fileRelativePath,
@@ -234,7 +234,11 @@ export function EditorPage(props: Props) {
       resolved={(file) => (
         <>
           <Page>
-            <EditorToolbar workspaceFile={file.workspaceFile} editor={webToolsEditor?.editor} />
+            <EditorToolbar
+              workspaceFile={file.workspaceFile}
+              editor={webToolsEditor?.editor}
+              onValidate={onLazyValidate}
+            />
             <Divider />
             <EditorPageDockDrawer
               ref={editorPageDockRef}
diff --git a/packages/serverless-logic-web-tools/src/editor/EditorToolbar.tsx b/packages/serverless-logic-web-tools/src/editor/EditorToolbar.tsx
index 60ab0e40cd..83b12ebd2a 100644
--- a/packages/serverless-logic-web-tools/src/editor/EditorToolbar.tsx
+++ b/packages/serverless-logic-web-tools/src/editor/EditorToolbar.tsx
@@ -43,6 +43,7 @@ import {
 import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
 import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
 import { AngleLeftIcon } from "@patternfly/react-icons/dist/js/icons/angle-left-icon";
+import { PlayIcon } from "@patternfly/react-icons/dist/js/icons/play-icon";
 import { ArrowCircleUpIcon } from "@patternfly/react-icons/dist/js/icons/arrow-circle-up-icon";
 import { CaretDownIcon } from "@patternfly/react-icons/dist/js/icons/caret-down-icon";
 import { OutlinedHddIcon } from "@patternfly/react-icons/dist/js/icons/outlined-hdd-icon";
@@ -104,6 +105,7 @@ import { ConfirmDeleteModal } from "../table";
 export interface Props {
   editor: EmbeddedEditorRef | undefined;
   workspaceFile: WorkspaceFile;
+  onValidate: () => void;
 }
 
 const showWhenSmall: ToolbarItemProps["visibility"] = {
@@ -938,6 +940,24 @@ If you are, it means that creating this Gist failed and it can safely be deleted
     );
   }, [workspaces, props.workspaceFile, githubAuthInfo, comittingAlert, commitSuccessAlert]);
 
+  const validateDropdownItem = useMemo(() => {
+    return isOfKind("yard", props.workspaceFile.name)
+      ? [
+          <DropdownItem
+            key={"validate-dropdown-item"}
+            icon={<PlayIcon />}
+            onClick={async () => {
+              props.onValidate();
+            }}
+            description={"Run model validation"}
+            ouiaId={"commit-button"}
+          >
+            Validate
+          </DropdownItem>,
+        ]
+      : [];
+  }, [props]);
+
   const pushSuccessAlert = useGlobalAlert(
     useCallback(
       ({ close }) => {
@@ -1724,7 +1744,12 @@ If you are, it means that creating this Gist failed and it can safely be deleted
                       <KebabDropdown
                         id={"kebab-lg"}
                         state={[isLargeKebabOpen, setLargeKebabOpen]}
-                        items={[deleteFileDropdownItem, <Divider key={"divider-0"} />, createSavePointDropdownItem]}
+                        items={[
+                          deleteFileDropdownItem,
+                          <Divider key={"divider-0"} />,
+                          createSavePointDropdownItem,
+                          ...validateDropdownItem,
+                        ]}
                       />
                     </ToolbarItem>
                     <ToolbarItem visibility={showWhenSmall} style={{ marginRight: 0 }}>
@@ -1735,6 +1760,7 @@ If you are, it means that creating this Gist failed and it can safely be deleted
                           deleteFileDropdownItem,
                           <Divider key={"divider-0"} />,
                           createSavePointDropdownItem,
+                          ...validateDropdownItem,
                           <Divider key={"divider-1"} />,
                           ...shareDropdownItems,
                           ...(!canBeDeployed
diff --git a/packages/serverless-logic-web-tools/src/editor/hooks/useEditorNotifications.tsx b/packages/serverless-logic-web-tools/src/editor/hooks/useEditorNotifications.tsx
index e6d75a4936..220e9ac1e9 100644
--- a/packages/serverless-logic-web-tools/src/editor/hooks/useEditorNotifications.tsx
+++ b/packages/serverless-logic-web-tools/src/editor/hooks/useEditorNotifications.tsx
@@ -33,12 +33,20 @@ interface HookArgs {
 export function useEditorNotifications(args: HookArgs) {
   const { webToolsEditor, content, fileRelativePath } = { ...args };
   const [notifications, setNotifications] = useState<Notification[]>([]);
+  const [lazyNotifications, setLazyNotifications] = useState<Notification[]>([]);
   const editorDispatch = useEditorDispatch();
 
   useEffect(() => {
     editorDispatch.setNotifications(notifications);
   }, [editorDispatch, notifications]);
 
+  const onLazyValidate = useCallback(async () => {
+    if (!webToolsEditor?.editor) {
+      return;
+    }
+    setLazyNotifications(await webToolsEditor.editor.validate());
+  }, [webToolsEditor]);
+
   useCancelableEffect(
     useCallback(
       ({ canceled }) => {
@@ -70,13 +78,13 @@ export function useEditorNotifications(args: HookArgs) {
                   },
                 } as Notification)
             );
-            setNotifications(mappedDiagnostics);
+            setNotifications([...mappedDiagnostics, ...lazyNotifications]);
           })
           .catch((e) => console.error(e));
       },
-      [content, fileRelativePath, webToolsEditor]
+      [content, fileRelativePath, webToolsEditor, lazyNotifications]
     )
   );
 
-  return notifications;
+  return { notifications, onLazyValidate };
 }
diff --git a/packages/serverless-logic-web-tools/webpack.config.ts b/packages/serverless-logic-web-tools/webpack.config.ts
index 9d996a5520..7de03b0bad 100644
--- a/packages/serverless-logic-web-tools/webpack.config.ts
+++ b/packages/serverless-logic-web-tools/webpack.config.ts
@@ -149,6 +149,10 @@ export default async (env: any, argv: any) => {
                 to: "./dashbuilder-client",
                 globOptions: { ignore: ["**/WEB-INF/**/*"] }, // "**/*.html" omitted because dashbuilder-client/index.html is needed
               },
+              {
+                from: path.resolve(__dirname, "node_modules/@kie-tools/yard-validator/dist/yard-validator-worker.js"),
+                to: "./yard-validator-worker.js",
+              },
             ],
           }),
           new ProvidePlugin({
diff --git a/packages/yard-editor/dev-webapp/webpack.config.js b/packages/yard-editor/dev-webapp/webpack.config.js
index f03f967422..168d29d76e 100644
--- a/packages/yard-editor/dev-webapp/webpack.config.js
+++ b/packages/yard-editor/dev-webapp/webpack.config.js
@@ -46,6 +46,10 @@ module.exports = (env) =>
             from: path.resolve(__dirname, "./static/envelope/yard-editor-envelope.html"),
             to: "./yard-editor-envelope.html",
           },
+          {
+            from: path.resolve(__dirname, "../node_modules/@kie-tools/yard-validator/dist/yard-validator-worker.js"),
+            to: "./yard-validator-worker.js",
+          },
         ],
       }),
       new MonacoWebpackPlugin({
diff --git a/packages/yard-editor/package.json b/packages/yard-editor/package.json
index 9b989a3422..1b1100d20d 100644
--- a/packages/yard-editor/package.json
+++ b/packages/yard-editor/package.json
@@ -38,6 +38,7 @@
     "@kie-tools-core/workspace": "workspace:*",
     "@kie-tools/i18n-common-dictionary": "workspace:*",
     "@kie-tools/yard-language-service": "workspace:*",
+    "@kie-tools/yard-validator": "workspace:*",
     "@patternfly/react-core": "^4.276.6",
     "@patternfly/react-icons": "^4.93.6",
     "@types/js-yaml": "^4.0.5",
diff --git a/packages/yard-editor/src/editor/YardEditorView.tsx b/packages/yard-editor/src/editor/YardEditorView.tsx
index f8059fa021..6ebe4f89d1 100644
--- a/packages/yard-editor/src/editor/YardEditorView.tsx
+++ b/packages/yard-editor/src/editor/YardEditorView.tsx
@@ -22,6 +22,7 @@ import * as React from "react";
 import { YardEditor } from "./YardEditor";
 import { YardEditorApi, YardEditorChannelApi } from "../api";
 import { Position } from "monaco-editor";
+import { validationPromise } from "@kie-tools/yard-validator/dist/";
 
 export class YardEditorView implements Editor {
   private readonly editorRef: React.RefObject<YardEditorApi>;
@@ -29,6 +30,7 @@ export class YardEditorView implements Editor {
   public af_isReact = true;
   public af_componentId: "yard-editor";
   public af_componentTitle: "Yard Editor";
+  private path: string;
 
   constructor(
     private readonly envelopeContext: KogitoEditorEnvelopeContextType<YardEditorChannelApi>,
@@ -37,8 +39,8 @@ export class YardEditorView implements Editor {
     this.editorRef = React.createRef<YardEditorApi>();
     this.initArgs = initArgs;
   }
-
   public setContent(path: string, content: string): Promise<void> {
+    this.path = path;
     return this.editorRef.current!.setContent(path, content);
   }
 
@@ -74,7 +76,22 @@ export class YardEditorView implements Editor {
   }
 
   public async validate(): Promise<Notification[]> {
-    return this.editorRef.current!.validate();
+    let result: Notification[] = [];
+    return this.editorRef
+      .current!.getContent()
+      .then((value) => {
+        return validationPromise(value);
+      })
+      .then((value) => {
+        result = result.concat(value);
+        return this.editorRef.current!.validate();
+      })
+      .then((value) => {
+        result = result.concat(value);
+        return new Promise<Notification[]>((resolve) => {
+          resolve(result);
+        });
+      });
   }
 
   public async setTheme(theme: EditorTheme) {
diff --git a/packages/yard-model/LICENSE b/packages/yard-model/LICENSE
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/packages/yard-model/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/packages/yard-model/env/index.js b/packages/yard-model/env/index.js
new file mode 100644
index 0000000000..425fad9efe
--- /dev/null
+++ b/packages/yard-model/env/index.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+const { varsWithName, composeEnv } = require("@kie-tools-scripts/build-env");
+
+module.exports = composeEnv([require("@kie-tools/root-env/env")], {
+  vars: varsWithName({}),
+  get env() {
+    return {
+      yardModel: {
+        version: require("../package.json").version,
+      },
+    };
+  },
+});
diff --git a/packages/yard-model/install.js b/packages/yard-model/install.js
new file mode 100644
index 0000000000..aa46eae8f3
--- /dev/null
+++ b/packages/yard-model/install.js
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+const buildEnv = require("./env");
+const { setup } = require("@kie-tools/maven-config-setup-helper");
+
+setup(`
+    -Drevision=${buildEnv.env.yardModel.version}
+`);
diff --git a/packages/yard-model/package.json b/packages/yard-model/package.json
new file mode 100644
index 0000000000..8ccb6117fd
--- /dev/null
+++ b/packages/yard-model/package.json
@@ -0,0 +1,48 @@
+{
+  "private": false,
+  "name": "@kie-tools/yard-model",
+  "version": "0.0.0",
+  "description": "",
+  "license": "Apache-2.0",
+  "keywords": [],
+  "homepage": "https://github.com/kiegroup/kie-tools",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/kiegroup/kie-tools.git"
+  },
+  "bugs": {
+    "url": "https://github.com/kiegroup/kie-tools/issues"
+  },
+  "scripts": {
+    "build:dev": "run-script-os",
+    "build:dev:darwin:linux": "pnpm install:mvnw && mvn clean install -DskipTests",
+    "build:dev:win32": "pnpm install:mvnw && pnpm powershell \"mvn clean install `-DskipTests\"",
+    "build:prod": "pnpm lint && run-script-os",
+    "build:prod:darwin:linux": "pnpm install:mvnw && mvn clean install -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)",
+    "build:prod:win32": "pnpm install:mvnw && pnpm powershell \"mvn clean install `-DskipTests=$(build-env tests.run --not) `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"",
+    "install": "node install.js",
+    "install:mvnw": "run-script-os",
+    "install:mvnw:darwin:linux": "mvn wrapper:wrapper",
+    "install:mvnw:win32": "pnpm powershell \"mvn wrapper:wrapper\"",
+    "lint": "echo 'Linting'",
+    "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command"
+  },
+  "dependencies": {
+    "@kie-tools-core/notifications": "workspace:*"
+  },
+  "devDependencies": {
+    "@kie-tools/maven-config-setup-helper": "workspace:*",
+    "@kie-tools/root-env": "workspace:*",
+    "copy-webpack-plugin": "^11.0.0",
+    "rimraf": "^3.0.2",
+    "run-script-os": "^1.1.6",
+    "typescript": "^4.6.2",
+    "webpack": "^5.88.2"
+  },
+  "kieTools": {
+    "requiredPreinstalledCliCommands": [
+      "java",
+      "mvn"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/packages/yard-model/pom.xml b/packages/yard-model/pom.xml
new file mode 100644
index 0000000000..568bbda361
--- /dev/null
+++ b/packages/yard-model/pom.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" ?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+  -->
+<project
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
+  xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.kie.kogito</groupId>
+    <artifactId>yard-model</artifactId>
+    <version>${revision}</version>
+
+    <licenses>
+        <license>
+            <name>Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <properties>
+        <yaml.mapper>0.4</yaml.mapper>
+        <helper.maven.plugin>3.2.0</helper.maven.plugin>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.treblereel.gwt.yaml.mapper</groupId>
+            <artifactId>common</artifactId>
+            <version>${yaml.mapper}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.treblereel.gwt.yaml.mapper</groupId>
+            <artifactId>processor</artifactId>
+            <version>${yaml.mapper}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>${helper.maven.plugin}</version>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>target/generated-sources/annotations</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/packages/yard-model/src/main/java/org/yard/model/DecisionLogic.java b/packages/yard-model/src/main/java/org/yard/model/DecisionLogic.java
new file mode 100644
index 0000000000..eca6770d60
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/DecisionLogic.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+
+import org.treblereel.gwt.yaml.api.annotation.YamlSubtype;
+import org.treblereel.gwt.yaml.api.annotation.YamlTypeInfo;
+
+@YamlTypeInfo(
+        key = "type",
+        value = {
+                @YamlSubtype(alias = "DecisionTable", type = DecisionTable.class),
+                @YamlSubtype(alias = "LiteralExpression", type = LiteralExpression.class)
+        })
+public interface DecisionLogic {
+}
diff --git a/packages/yard-model/src/main/java/org/yard/model/DecisionTable.java b/packages/yard-model/src/main/java/org/yard/model/DecisionTable.java
new file mode 100644
index 0000000000..4513608cab
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/DecisionTable.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+
+import org.treblereel.gwt.yaml.api.annotation.YAMLMapper;
+import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer;
+import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer;
+import org.yard.model.RuleDefSerializer;
+
+import java.util.List;
+
+@YAMLMapper
+public class DecisionTable implements DecisionLogic {
+    private List<String> inputs;
+    private String hitPolicy = "ANY";
+    @Deprecated
+    private List<String> outputComponents;
+    @YamlTypeSerializer(RuleDefSerializer.class)
+    @YamlTypeDeserializer(RuleDefSerializer.class)
+    private List rules;
+
+    public void setInputs(List<String> inputs) {
+        this.inputs = inputs;
+    }
+
+    public void setOutputComponents(List<String> outputComponents) {
+        this.outputComponents = outputComponents;
+    }
+
+    public List<String> getInputs() {
+        return inputs;
+    }
+
+    @Deprecated
+    public List<String> getOutputComponents() {
+        return outputComponents;
+    }
+
+    public String getHitPolicy() {
+        return hitPolicy;
+    }
+
+    public void setHitPolicy(String hitPolicy) {
+        this.hitPolicy = hitPolicy;
+    }
+
+    public List getRules() {
+        return rules;
+    }
+
+    public void setRules(List rules) {
+        this.rules = rules;
+    }
+
+}
\ No newline at end of file
diff --git a/packages/yard-model/src/main/java/org/yard/model/Element.java b/packages/yard-model/src/main/java/org/yard/model/Element.java
new file mode 100644
index 0000000000..7339d80039
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/Element.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+
+import org.treblereel.gwt.yaml.api.annotation.YAMLMapper;
+
+import java.util.List;
+
+@YAMLMapper
+public class Element {
+
+    private String name;
+    private String type;
+    private List<String> requirements;
+    private DecisionLogic logic;
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public void setRequirements(List<String> requirements) {
+        this.requirements = requirements;
+    }
+
+    public void setLogic(DecisionLogic logic) {
+        this.logic = logic;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public List<String> getRequirements() {
+        return requirements;
+    }
+
+    public DecisionLogic getLogic() {
+        return logic;
+    }
+}
\ No newline at end of file
diff --git a/packages/yard-model/src/main/java/org/yard/model/InlineRule.java b/packages/yard-model/src/main/java/org/yard/model/InlineRule.java
new file mode 100644
index 0000000000..59f2f2e45e
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/InlineRule.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+import java.util.List;
+
+public class InlineRule implements Rule {
+
+    private final int rowNumber;
+    public List def;
+
+    public InlineRule(int rowNumber, List data) {
+        this.rowNumber = rowNumber;
+        this.def = data;
+    }
+
+    @Override
+    public int getRowNumber() {
+        return rowNumber;
+    }
+
+    public List getDef() {
+        return def;
+    }
+
+    public void setDef(List def) {
+        this.def = def;
+    }
+}
diff --git a/packages/yard-model/src/main/java/org/yard/model/Input.java b/packages/yard-model/src/main/java/org/yard/model/Input.java
new file mode 100644
index 0000000000..2f25d7882a
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/Input.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+
+import org.treblereel.gwt.yaml.api.annotation.YAMLMapper;
+
+@YAMLMapper
+public class Input {
+    private String name;
+    private String type;
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getType() {
+        return type;
+    }
+}
\ No newline at end of file
diff --git a/packages/yard-model/src/main/java/org/yard/model/LiteralExpression.java b/packages/yard-model/src/main/java/org/yard/model/LiteralExpression.java
new file mode 100644
index 0000000000..160ed30754
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/LiteralExpression.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+
+import org.treblereel.gwt.yaml.api.annotation.YAMLMapper;
+
+@YAMLMapper
+public class LiteralExpression implements DecisionLogic {
+    private String expression;
+
+    public void setExpression(String expression) {
+        this.expression = expression;
+    }
+
+    public String getExpression() {
+        return expression;
+    }
+}
\ No newline at end of file
diff --git a/packages/yard-model/src/main/java/org/yard/model/Operators.java b/packages/yard-model/src/main/java/org/yard/model/Operators.java
new file mode 100644
index 0000000000..672eb3b088
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/Operators.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+import java.util.Objects;
+
+/**
+ * Interface instead of enum due to possible custom operators.
+ */
+public interface Operators {
+    String NOT_EQUALS = "!=";
+    String EQUALS = "=";
+    String GREATER_OR_EQUAL = ">=";
+    String GREATER_THAN = ">";
+    String LESS_OR_EQUAL = "<=";
+    String LESS_THAN = "<";
+
+    String[] ALL = {EQUALS, LESS_OR_EQUAL, LESS_THAN, GREATER_OR_EQUAL, GREATER_THAN, NOT_EQUALS};
+
+    static int compare(final String operator,
+                       final String other) {
+        return getWeight(operator) - getWeight(other);
+    }
+
+    static int getWeight(final String operator) {
+        for (int i = 0; i < ALL.length; i++) {
+            if (Objects.equals(operator, ALL[i])) {
+                return i;
+            }
+        }
+        return 0;
+    }
+}
diff --git a/packages/yard-model/src/main/java/org/yard/model/Rule.java b/packages/yard-model/src/main/java/org/yard/model/Rule.java
new file mode 100644
index 0000000000..98944a05db
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/Rule.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+public interface Rule {
+    int getRowNumber();
+}
diff --git a/packages/yard-model/src/main/java/org/yard/model/RuleDefSerializer.java b/packages/yard-model/src/main/java/org/yard/model/RuleDefSerializer.java
new file mode 100644
index 0000000000..2d984cf22b
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/RuleDefSerializer.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+
+import org.treblereel.gwt.yaml.api.node.YamlMapping;
+import org.treblereel.gwt.yaml.api.node.YamlNode;
+import org.treblereel.gwt.yaml.api.node.YamlSequence;
+import org.treblereel.gwt.yaml.api.YAMLDeserializer;
+import org.treblereel.gwt.yaml.api.YAMLSerializer;
+import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException;
+import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext;
+import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RuleDefSerializer
+        implements YAMLSerializer<Object>, YAMLDeserializer<Object> {
+
+    private int rowNumber = 1;
+    @Override
+    public Object deserialize(YamlMapping yamlMapping,
+                              String s,
+                              YAMLDeserializationContext yamlDeserializationContext) throws YAMLDeserializationException {
+        return deserialize(yamlMapping.getNode(s), yamlDeserializationContext);
+    }
+
+    @Override
+    public Object deserialize(YamlNode yamlNode,
+                              YAMLDeserializationContext yamlDeserializationContext) {
+        if (yamlNode instanceof YamlSequence) {
+            final List<Comparable> items = getItems(yamlNode);
+            return new InlineRule(rowNumber++, items);
+
+        } else if (yamlNode instanceof YamlMapping) {
+            final WhenThenRule whenThenRule = new WhenThenRule(rowNumber++);
+            final YamlNode when = ((YamlMapping) yamlNode).getNode("when");
+            final YamlNode then = ((YamlMapping) yamlNode).getNode("then");
+            whenThenRule.setWhen(getItems(when));
+            whenThenRule.setThen(then.asScalar().value());
+            return whenThenRule;
+        }
+        return new IllegalArgumentException("Unknown rule format.");
+    }
+
+    private List<Comparable> getItems(final YamlNode yamlNode) {
+        final List<Comparable> result = new ArrayList<>();
+        if (yamlNode instanceof YamlSequence) {
+            ((YamlSequence) yamlNode).iterator().forEachRemaining(x -> {
+                final Comparable value = (Comparable) x.asScalar().value();
+                result.add(value);
+            });
+        }
+        return result;
+    }
+
+    @Override
+    public void serialize(YamlMapping yamlMapping,
+                          String s,
+                          Object objects,
+                          YAMLSerializationContext yamlSerializationContext) {
+        // Not needed, we never serialize.
+    }
+
+    @Override
+    public void serialize(YamlSequence yamlSequence,
+                          Object objects,
+                          YAMLSerializationContext yamlSerializationContext) {
+        // Not needed, we never serialize.
+    }
+}
diff --git a/packages/yard-model/src/main/java/org/yard/model/WhenThenRule.java b/packages/yard-model/src/main/java/org/yard/model/WhenThenRule.java
new file mode 100644
index 0000000000..2293dadc7a
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/WhenThenRule.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+import java.util.List;
+
+public class WhenThenRule implements Rule {
+
+    private final int rowNumber;
+    private List when;
+    private Object then;
+
+    public WhenThenRule(int rowNumber) {
+        this.rowNumber = rowNumber;
+    }
+
+    @Override
+    public int getRowNumber() {
+        return rowNumber;
+    }
+
+    public List getWhen() {
+        return when;
+    }
+
+    public Object getThen() {
+        return then;
+    }
+
+    public void setWhen(List when) {
+        this.when = when;
+    }
+
+    public void setThen(Object then) {
+        this.then = then;
+    }
+}
diff --git a/packages/yard-model/src/main/java/org/yard/model/WhenThenRuleThenSerializer.java b/packages/yard-model/src/main/java/org/yard/model/WhenThenRuleThenSerializer.java
new file mode 100644
index 0000000000..7debaed52e
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/WhenThenRuleThenSerializer.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+import org.treblereel.gwt.yaml.api.YAMLDeserializer;
+import org.treblereel.gwt.yaml.api.YAMLSerializer;
+import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException;
+import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext;
+import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext;
+import org.treblereel.gwt.yaml.api.node.YamlMapping;
+import org.treblereel.gwt.yaml.api.node.YamlNode;
+import org.treblereel.gwt.yaml.api.node.YamlSequence;
+
+import java.util.Locale;
+
+public class WhenThenRuleThenSerializer
+        implements YAMLSerializer<Object>, YAMLDeserializer<Object> {
+    @Override
+    public Object deserialize(YamlMapping yamlMapping, String key, YAMLDeserializationContext yamlDeserializationContext) throws YAMLDeserializationException {
+        return deserialize(yamlMapping.getNode(key), yamlDeserializationContext);
+    }
+
+    @Override
+    public Object deserialize(YamlNode yamlNode, YAMLDeserializationContext yamlDeserializationContext) {
+        if (yamlNode == null || yamlNode.isEmpty()) {
+            return null;
+        }
+        return yamlNode.<String>asScalar().value().toLowerCase(Locale.ROOT);
+    }
+
+    @Override
+    public void serialize(YamlMapping yamlMapping, String s, Object o, YAMLSerializationContext yamlSerializationContext) {
+        // Not needed, we never serialize.
+    }
+
+    @Override
+    public void serialize(YamlSequence yamlSequence, Object o, YAMLSerializationContext yamlSerializationContext) {
+        // Not needed, we never serialize.
+    }
+}
diff --git a/packages/yard-model/src/main/java/org/yard/model/YaRD.java b/packages/yard-model/src/main/java/org/yard/model/YaRD.java
new file mode 100644
index 0000000000..254b5a2ca8
--- /dev/null
+++ b/packages/yard-model/src/main/java/org/yard/model/YaRD.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.model;
+
+
+import org.treblereel.gwt.yaml.api.annotation.YAMLMapper;
+
+import java.util.List;
+
+@YAMLMapper
+public class YaRD {
+
+    private String specVersion = "alpha";
+    private String kind = "YaRD";
+    private String name;
+    private String expressionLang;
+    private List<Input> inputs;
+    private List<Element> elements;
+
+    public void setInputs(List<Input> inputs) {
+        this.inputs = inputs;
+    }
+
+    public void setElements(List<Element> elements) {
+        this.elements = elements;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getExpressionLang() {
+        return expressionLang;
+    }
+
+    public void setExpressionLang(String expressionLang) {
+        this.expressionLang = expressionLang;
+    }
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public String getSpecVersion() {
+        return specVersion;
+    }
+
+    public void setSpecVersion(String specVersion) {
+        this.specVersion = specVersion;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<Input> getInputs() {
+        return inputs;
+    }
+
+    public List<Element> getElements() {
+        return elements;
+    }
+}
\ No newline at end of file
diff --git a/packages/yard-validator-worker/README.md b/packages/yard-validator-worker/README.md
new file mode 100644
index 0000000000..fb332661ef
--- /dev/null
+++ b/packages/yard-validator-worker/README.md
@@ -0,0 +1,22 @@
+## YARD validator
+
+###### Module for YARD (Yet Another Rule Definition) validation.
+
+### Description
+
+This module contains a standalone J2CL/Java module that can be used to validate YARD file. J2CL version is recommended
+to be ran in a webworker due to the heavy load.
+
+There is a static test page at demo/demo.html. Build the project before running it.
+
+### Validation items currently covered
+
+- Subsumption, when one row "eats" another by covering the same constraints as the subsumed row.
+- Redundant rows. Either the same result is duplicated or one row is useless.
+
+### Validation item ideas for future
+
+- Masked rows, when a row subsumes another, but also blocks the subsumed row from getting ever activated.
+- Conflicting rows. Two rows return different results with overlapping or subsuming constraints.
+- Overlapping rows. Two rows can be activated by the same data, but the rows do not subsume each other.
+- Gaps between the rows
diff --git a/packages/yard-validator-worker/demo/demo.html b/packages/yard-validator-worker/demo/demo.html
new file mode 100644
index 0000000000..8b6863615a
--- /dev/null
+++ b/packages/yard-validator-worker/demo/demo.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Example</title>
+  </head>
+  <body>
+    <script>
+      function validationPromise(yaml) {
+        const promise = new Promise(function (resolve, reject) {
+          const worker = new Worker("../dist/yard-validator-worker.js");
+          console.log("Starting web worker.");
+          worker.postMessage("ENABLE_LOGGING");
+          worker.postMessage(yaml);
+          worker.onmessage = (e) => {
+            if (e.data.startsWith("Log")) {
+              console.log(e.data);
+            } else {
+              resolve(e.data);
+              worker.terminate();
+            }
+          };
+        });
+        return promise;
+      }
+
+      function validate() {
+        let message = document.getElementById("text-area").value;
+        validationPromise(message).then(
+          function (result) {
+            document.getElementById("result-area").value = "Done\n" + result;
+          },
+          function (error) {}
+        );
+      }
+    </script>
+    <textarea id="text-area" style="height: 800px; width: 600px">
+
+specVersion: alpha
+kind: YaRD
+name: "Traffic Violation"
+expressionLang: alpha
+inputs:
+  - name: "Driver"
+    type: "http://myapi.org/jsonSchema.json#Driver"
+  - name: "Violation"
+    type: "http://myapi.org/jsonSchema.json#Violation"
+elements:
+  - name: "Fine"
+    type: Decision
+    requirements: ["Violation"]
+    logic:
+      type: DecisionTable
+      inputs: ["Violation.type", "Violation.Actual Speed - Violation.Speed Limit"]
+      outputComponents: ["Amount", "Points"]
+      rules:
+        - ['="speed"', "[10..30)", 500, 3]
+        - ['="speed"', ">= 30", 1000, 7]
+        - ['="speed"', ">= 60", 1000, 7]
+        - ['="parking"', "-", 100, 1]
+        - ['="driving under the influence"', "-", 1000, 5]
+  - name: "Should the driver be suspended?"
+    type: Decision
+    requirements: ["Driver", "Fine"]
+    logic:
+      type: LiteralExpression
+      expression: 'if Driver.Points + Fine.Points >= 20 then "Yes" else "No"'
+
+    </textarea>
+    <button onclick="validate()" style="vertical-align: top">Validate</button>
+    <textarea id="result-area" style="height: 800px; width: 600px" readonly></textarea>
+  </body>
+</html>
diff --git a/packages/yard-validator-worker/env/index.js b/packages/yard-validator-worker/env/index.js
new file mode 100644
index 0000000000..26e1811bd5
--- /dev/null
+++ b/packages/yard-validator-worker/env/index.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+const { varsWithName, composeEnv } = require("@kie-tools-scripts/build-env");
+
+module.exports = composeEnv([require("@kie-tools/root-env/env")], {
+  vars: varsWithName({}),
+  get env() {
+    return {
+      yardValidator: {
+        version: require("../package.json").version,
+      },
+    };
+  },
+});
diff --git a/packages/yard-validator-worker/install.js b/packages/yard-validator-worker/install.js
new file mode 100644
index 0000000000..4247286a3f
--- /dev/null
+++ b/packages/yard-validator-worker/install.js
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+const buildEnv = require("./env");
+const { setup } = require("@kie-tools/maven-config-setup-helper");
+
+setup(`
+    -Drevision=${buildEnv.env.yardValidator.version}
+`);
diff --git a/packages/yard-validator-worker/package.json b/packages/yard-validator-worker/package.json
new file mode 100644
index 0000000000..023d2a6fde
--- /dev/null
+++ b/packages/yard-validator-worker/package.json
@@ -0,0 +1,50 @@
+{
+  "private": false,
+  "name": "@kie-tools/yard-validator-worker",
+  "version": "0.0.0",
+  "description": "",
+  "license": "Apache-2.0",
+  "keywords": [],
+  "homepage": "https://github.com/kiegroup/kie-tools",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/kiegroup/kie-tools.git"
+  },
+  "bugs": {
+    "url": "https://github.com/kiegroup/kie-tools/issues"
+  },
+  "scripts": {
+    "build:dev": "rimraf dist && run-script-os && pnpm copy:webworker",
+    "build:dev:darwin:linux": "pnpm install:mvnw && mvn clean install -DskipTests",
+    "build:dev:win32": "pnpm install:mvnw && pnpm powershell \"mvn clean install `-DskipTests\"",
+    "build:prod": "pnpm lint && run-script-os && pnpm copy:webworker",
+    "build:prod:darwin:linux": "pnpm install:mvnw && mvn clean install -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)",
+    "build:prod:win32": "pnpm install:mvnw && pnpm powershell \"mvn clean install `-DskipTests=$(build-env tests.run --not) `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"",
+    "copy:webworker": "copyfiles -f target/worker/yard-validator-worker/yard-validator-worker.js dist",
+    "install": "node install.js",
+    "install:mvnw": "run-script-os",
+    "install:mvnw:darwin:linux": "mvn wrapper:wrapper",
+    "install:mvnw:win32": "pnpm powershell \"mvn wrapper:wrapper\"",
+    "lint": "echo 'Linting'",
+    "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command"
+  },
+  "dependencies": {
+    "@kie-tools-core/notifications": "workspace:*",
+    "@kie-tools/yard-model": "workspace:*"
+  },
+  "devDependencies": {
+    "@kie-tools/maven-config-setup-helper": "workspace:*",
+    "@kie-tools/root-env": "workspace:*",
+    "@kie-tools/tsconfig": "workspace:*",
+    "copyfiles": "^2.4.1",
+    "rimraf": "^3.0.2",
+    "run-script-os": "^1.1.6",
+    "typescript": "^4.6.2"
+  },
+  "kieTools": {
+    "requiredPreinstalledCliCommands": [
+      "java",
+      "mvn"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/packages/yard-validator-worker/pom.xml b/packages/yard-validator-worker/pom.xml
new file mode 100644
index 0000000000..3c30e4afc4
--- /dev/null
+++ b/packages/yard-validator-worker/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" ?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+  -->
+<project
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
+  xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.kie.kogito</groupId>
+    <artifactId>yard-validator-worker</artifactId>
+    <version>${revision}</version>
+
+    <licenses>
+        <license>
+            <name>Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <properties>
+        <yaml.mapper>0.4</yaml.mapper>
+        <org.jresearch.gwt.time>2.0.10</org.jresearch.gwt.time>
+        <compiler-plugin.version>3.8.1</compiler-plugin.version>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
+        <version.junit>4.13.1</version.junit>
+        <j2cl.maven.plugin.version>0.20</j2cl.maven.plugin.version>
+        <version.org.junit>4.13.1</version.org.junit>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.treblereel.gwt.yaml.mapper</groupId>
+            <artifactId>common</artifactId>
+            <version>${yaml.mapper}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.kie.kogito</groupId>
+            <artifactId>yard-model</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.kie.kogito</groupId>
+            <artifactId>yard-model</artifactId>
+            <version>${project.version}</version>
+            <classifier>sources</classifier>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${version.org.junit}</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>../src/main/resources</directory>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>com.vertispan.j2cl</groupId>
+                <artifactId>j2cl-maven-plugin</artifactId>
+                <version>${j2cl.maven.plugin.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <webappDirectory>${project.build.directory}/worker</webappDirectory>
+                    <compilationLevel>ADVANCED</compilationLevel>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/CustomTreeSet.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/CustomTreeSet.java
new file mode 100644
index 0000000000..58c9595f5e
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/CustomTreeSet.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+import org.yard.model.Operators;
+import org.yard.validator.key.ColumnKey;
+import org.yard.validator.key.Key;
+import org.yard.validator.key.OperatorValueKey;
+
+import java.util.*;
+
+public class CustomTreeSet {
+
+    private final TreeSet<Key> innerSet;
+
+    private final Set<ColumnKey> equalColumns = new HashSet<>();
+
+    public CustomTreeSet() {
+        innerSet = new TreeSet<>(getComparator());
+    }
+
+    private static Comparator<Key> getComparator() {
+        return (a, b) -> {
+            final int compareResult = compareKeys(a, b);
+            if (compareResult == 0) {
+                if (a instanceof OperatorValueKey
+                        && b instanceof OperatorValueKey) {
+                    return Operators.compare(
+                            ((OperatorValueKey) a).getOperator(),
+                            ((OperatorValueKey) b).getOperator());
+                } else {
+                    throw new IllegalArgumentException("What? Looks like it was not an OperatorValueKey.");
+                }
+            }
+            return compareResult;
+        };
+    }
+
+    private static int compareKeys(final Key a,
+            final Key b) {
+        if (a.getParent() instanceof Comparable
+                && b.getParent() instanceof Comparable) {
+            return ((Comparable) a.getParent()).compareTo(b.getParent());
+        }
+        return -1;
+    }
+
+    public Set<ColumnKey> getEqualColumns() {
+        return equalColumns;
+    }
+
+    public int getHash(final Set<ColumnKey> bundleKeys) {
+        int result = 0;
+
+        // Inner HashMap would speed this up, but not sure if it is worth it.
+        // All the ParentKeys that we are looking for are like on the front of the list.
+        for (Key key : innerSet) {
+            if (bundleKeys.contains(key.getParent())) {
+                result = 31 * result + ((OperatorValueKey) key).getValue().hashCode();
+            }
+        }
+
+        return result;
+    }
+
+    public boolean addAll(final CustomTreeSet c) {
+        if (c instanceof CustomTreeSet) {
+            equalColumns.addAll(((CustomTreeSet) c).equalColumns);
+        }
+        return innerSet.addAll(c.innerSet);
+    }
+
+    public boolean add(final Key o) {
+        if (o instanceof OperatorValueKey) {
+            if (Objects.equals(Operators.EQUALS, ((OperatorValueKey) o).getOperator())) {
+                equalColumns.add((ColumnKey) o.getParent());
+            }
+        }
+        return innerSet.add(o);
+    }
+
+    public boolean isEmpty() {
+        return innerSet.isEmpty();
+    }
+
+    public int size() {
+        return innerSet.size();
+    }
+
+    public Key[] toArray(final Key[] keys) {
+        return innerSet.toArray(keys);
+    }
+
+    @Override
+    public String toString() {
+        String result = "";
+
+        for (Key key : innerSet) {
+            result += key.toString();
+            result += "\n";
+        }
+
+        return result;
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/Issue.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/Issue.java
new file mode 100644
index 0000000000..8d11223369
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/Issue.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+import org.yard.validator.key.Location;
+
+import java.util.Arrays;
+
+public class Issue {
+    private String message;
+    private Location[] locations;
+
+    public Issue(final String message, final Location... locations) {
+        this.message = message;
+        this.locations = locations;
+    }
+
+    public Location[] getLocations() {
+        return locations;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public String toString() {
+        return "Issue{" +
+                "message='" + message + '\'' +
+                ", locations=" + Arrays.toString(locations) +
+                '}';
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/Parser.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/Parser.java
new file mode 100644
index 0000000000..6926262542
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/Parser.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+import org.yard.model.*;
+import org.yard.validator.key.*;
+import org.yard.validator.util.Date;
+import org.yard.validator.util.Logger;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+public class Parser {
+
+    private String hitPolicy;
+
+    public ParserResult parse(final String yaml) {
+
+        try {
+
+            final YaRD model = new YaRD_YamlMapperImpl().read(yaml);
+
+            Logger.log("YaRD model has been read.");
+            Logger.log("YaRD model name is " + model.getName());
+            final TreeMap<RowLocation, CustomTreeSet> result
+                    = visit(findTableStartRow(yaml), model);
+
+            return new ParserResult(result, hitPolicy.toUpperCase());
+        } catch (Exception e) {
+            Logger.log("Failed to parse YAML " + e.getMessage());
+            return new ParserResult(Collections.emptyMap(), "ANY");
+        }
+
+    }
+
+    private int findTableStartRow(final String yaml) {
+        final String[] split = yaml.split("\n");
+        for (int i = 0; i < split.length; i++) {
+            final String trim = split[i].trim();
+            if (Objects.equals("rules:", trim)) {
+                return i + 1;
+            }
+        }
+        return -1;
+    }
+
+    private TreeMap<RowLocation, CustomTreeSet> visit(
+            final int rulesRow,
+            final YaRD yard) {
+        final TreeMap<RowLocation, CustomTreeSet> result = new TreeMap<>();
+        for (final Element element : yard.getElements()) {
+            if (element.getLogic() instanceof DecisionTable) {
+                final DecisionTable dt = (DecisionTable) element.getLogic();
+
+                Logger.log("Hit policy is : " + hitPolicy);
+                hitPolicy = dt.getHitPolicy();
+
+                final List<Rule> rules = dt.getRules();
+                for (Rule rule : rules) {
+                    final RowLocation location = new RowLocation(
+                            rule.getRowNumber(),
+                            rule.getRowNumber() + rulesRow);
+                    if (rule instanceof WhenThenRule) {
+                        final CustomTreeSet keys = getWhenThenKeys(dt, (WhenThenRule) rule, location);
+                        if (!keys.isEmpty()) {
+                            result.put(location, keys);
+                        }
+                    } else if (rule instanceof InlineRule) {
+                        final CustomTreeSet keys = getInlineRuleKeys(dt, (InlineRule) rule, location);
+                        if (!keys.isEmpty()) {
+                            result.put(location, keys);
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    private CustomTreeSet getInlineRuleKeys(
+            final DecisionTable dt,
+            final InlineRule rule,
+            final RowLocation location) {
+        final CustomTreeSet keys = new CustomTreeSet();
+        int columnIndex = 0;
+        for (Object o : rule.getDef()) {
+            if (dt.getInputs().size() > columnIndex) {
+                final String input = dt.getInputs().get(columnIndex++);
+                final ColumnKey columnKey = new ColumnKey(input);
+                keys.addAll(
+                        getKeys(
+                                location,
+                                o,
+                                columnKey));
+            }
+        }
+        return keys;
+    }
+
+    private CustomTreeSet getWhenThenKeys(final DecisionTable dt,
+            final WhenThenRule r,
+            final RowLocation location) {
+        final CustomTreeSet keys = new CustomTreeSet();
+
+        int columnIndex = 0;
+        for (Object o : r.getWhen()) {
+            final String input = dt.getInputs().get(columnIndex++);
+            final ColumnKey columnKey = new ColumnKey(input);
+            keys.addAll(
+                    getKeys(
+                            location,
+                            o,
+                            columnKey));
+        }
+        return keys;
+    }
+
+    private CustomTreeSet getKeys(final RowLocation location,
+            final Object o,
+            final ColumnKey columnKey) {
+        final CustomTreeSet keys = new CustomTreeSet();
+        if (o instanceof Comparable) {
+            if (isSplit(o)) {
+                final String text = (String) o;
+                final String start = text.substring(0, text.indexOf(".."));
+                final String end = text.substring(text.indexOf("..") + 2);
+                final String operatorStart = resolveToOperator(start.charAt(0));
+                final String operatorEnd = resolveToOperator(end.charAt(end.length() - 1));
+                final Comparable valueStart = testType(start.substring(1));
+                final Comparable valueEnd = testType(end.substring(0, end.length() - 1));
+                keys.add(new OperatorValueKey(location, columnKey, operatorStart, valueStart));
+                keys.add(new OperatorValueKey(location, columnKey, operatorEnd, valueEnd));
+            } else {
+
+                final String operator = getOperator(o);
+                final Comparable value = getValue(o, operator);
+
+                if (value == null) {
+                    // no need to add nulls
+                } else if (operator == null) {
+                    keys.add(new ObjectKey(location, columnKey, (Comparable) o));
+                } else {
+                    keys.add(new OperatorValueKey(location, columnKey, operator, value));
+                }
+            }
+        }
+        return keys;
+    }
+
+    private String resolveToOperator(final char c) {
+        switch (c) {
+            case '(':
+                return Operators.GREATER_THAN;
+            case ')':
+                return Operators.LESS_THAN;
+            case '[':
+                return Operators.GREATER_OR_EQUAL;
+            case ']':
+                return Operators.LESS_OR_EQUAL;
+        }
+        throw new IllegalStateException("Ranged operator unknown.");
+    }
+
+    private boolean isSplit(final Object o) {
+        if (o instanceof String) {
+            return ((String) o).contains("..") && isRangeStart((String) o) && isRangeEnd((String) o);
+        }
+        return false;
+    }
+
+    private boolean isRangeEnd(final String text) {
+        return text.endsWith(")") || text.endsWith("]");
+    }
+
+    private boolean isRangeStart(final String text) {
+        return text.startsWith("(") || text.startsWith("[");
+    }
+
+    private Comparable getValue(final Object o,
+            final String operator) {
+        if (operator != null && o instanceof String) {
+            final String value = ((String) o).substring(operator.length());
+            return testType(value);
+        } else if (operator == null && o instanceof String && Objects.equals("-", ((String) o).trim())) {
+            return null;
+        }
+        return testType(o);
+    }
+
+    private Comparable testType(final Object o) {
+        if (o instanceof String) {
+            final String value = ((String) o).trim();
+            try {
+                return new BigDecimal(value);
+            } catch (NumberFormatException e) {
+                // Was a nice try, but no luck.
+            }
+            try {
+                return new Date(value);
+            } catch (IllegalArgumentException e) {
+                // Was a nice try, but no luck.
+            }
+            return value;
+        }
+        return null;
+    }
+
+    private String getOperator(final Object o) {
+        if (o instanceof String) {
+            final String text = (String) o;
+            for (final String operator : Operators.ALL) {
+                if (text.trim().startsWith(operator)) {
+                    return operator;
+                }
+            }
+        }
+
+        return null; // Null is fine
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/ParserResult.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/ParserResult.java
new file mode 100644
index 0000000000..9a73de0ab3
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/ParserResult.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+import org.yard.validator.key.RowLocation;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ParserResult {
+
+    private final Map<RowLocation, CustomTreeSet> result;
+    private final String hitPolicy;
+
+    public ParserResult(
+            final Map<RowLocation, CustomTreeSet> result,
+            final String hitPolicy
+    ) {
+        this.result = result;
+        this.hitPolicy = hitPolicy;
+    }
+
+    public Map<RowLocation, CustomTreeSet> getResult() {
+        return result;
+    }
+
+    public String getHitPolicy() {
+        return hitPolicy;
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/ReportBus.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/ReportBus.java
new file mode 100644
index 0000000000..a1cb2f306f
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/ReportBus.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+public interface ReportBus {
+    public void report(final Issue issue);
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/YardValidator.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/YardValidator.java
new file mode 100644
index 0000000000..8e3e409b3c
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/YardValidator.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+import jsinterop.annotations.JsConstructor;
+import jsinterop.annotations.JsMethod;
+import org.yard.validator.checks.Check;
+import org.yard.validator.checks.CheckProducer;
+import org.yard.validator.key.Location;
+import org.yard.validator.key.RowLocation;
+import org.yard.validator.runner.Runner;
+import org.yard.validator.util.Callback;
+import org.yard.validator.util.Logger;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class YardValidator {
+
+    private final ArrayList<String> log = new ArrayList<>();
+    private ParserResult parse;
+
+    @JsConstructor
+    public YardValidator() {
+    }
+
+    @JsMethod
+    public void setLogger(final Callback callback) {
+        Logger.startLogging(callback);
+    }
+
+    private void init(final String yaml) {
+
+        Logger.startLogging(s -> log.add("\"" + s + "\""));
+        Logger.log("Starting validator");
+
+        parse = new Parser().parse(yaml);
+    }
+
+    @JsMethod
+    public String validate(final String yaml) {
+        final ArrayList<String> issues = new ArrayList<>();
+        validate(yaml, issue -> {
+            final StringBuilder builder = new StringBuilder();
+            builder.append("{\"issue\":\"" + issue.getMessage() + "\"");
+            builder.append(",");
+            builder.append("\"locations\":[");
+
+            builder.append(Arrays.stream(issue.getLocations()).map(i -> {
+                final StringBuilder innerBuilder = new StringBuilder();
+                innerBuilder.append("{");
+                innerBuilder.append("\"rowInFile\":" + ((RowLocation) i).getActualRowNumberInFile() + ",");
+                innerBuilder.append("\"rowInTable\":" + ((RowLocation) i).getTableRowNumber());
+                innerBuilder.append("}");
+                return innerBuilder.toString();
+            }).collect(Collectors.joining(", ")));
+
+            builder.append("]}");
+            issues.add(builder.toString());
+        });
+        return "{\"log\":[" + log.toArray().toString() + "],\"result\":[" + issues.stream().collect(Collectors.joining(",")) + "]}";
+    }
+
+    public void validate(final String yaml, final ReportBus bus) {
+        try {
+            init(yaml);
+        } catch (final Exception e) {
+            Logger.log("Failed to initialize: " + e.getMessage());
+        }
+
+        new Runner(bus).run(getChecks());
+    }
+
+    private List<Check> getChecks() {
+        if (Objects.equals("COLLECT", parse.getHitPolicy())) {
+            return Collections.emptyList();
+        } else {
+            return CheckProducer.getChecks(parse);
+        }
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/app.js b/packages/yard-validator-worker/src/main/java/org/yard/validator/app.js
new file mode 100644
index 0000000000..c0a5ab5805
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/app.js
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+goog.module("org.yard.validator");
+
+const YardValidator = goog.require("org.yard.validator.YardValidator");
+
+const validator = new YardValidator();
+
+self.addEventListener("message", (e) => {
+  if (e.data === "ENABLE_LOGGING") {
+    validator.setLogger((e) => {
+      self.postMessage("Log: " + e);
+    });
+    self.postMessage("Log logger set up");
+  } else {
+    self.postMessage(validator.validate(e.data));
+  }
+});
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/Check.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/Check.java
new file mode 100644
index 0000000000..170828f393
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/Check.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.checks;
+
+import org.yard.validator.Issue;
+
+import java.util.Optional;
+
+public interface Check {
+    Optional<Issue> check();
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/CheckItem.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/CheckItem.java
new file mode 100644
index 0000000000..9461fbb5c1
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/CheckItem.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.checks;
+
+import org.yard.validator.CustomTreeSet;
+import org.yard.validator.key.Key;
+import org.yard.validator.key.Location;
+
+public class CheckItem {
+    private final int index;
+    private final Location location;
+    private final Key[] keys;
+
+    public CheckItem(final int index,
+                     final Location location,
+                     final CustomTreeSet keys) {
+
+        this.index = index;
+        this.location = location;
+        this.keys = keys.toArray(new Key[keys.size()]);
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public Location getLocation() {
+        return location;
+    }
+
+    public Key[] getKeys() {
+        return keys;
+    }
+
+    @Override
+    public String toString() {
+        return "CheckItem{" +
+                "location=" + location +
+                '}';
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/CheckProducer.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/CheckProducer.java
new file mode 100644
index 0000000000..876d9900b8
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/CheckProducer.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.checks;
+
+import org.yard.validator.CustomTreeSet;
+import org.yard.validator.ParserResult;
+import org.yard.validator.key.ColumnKey;
+import org.yard.validator.key.Location;
+import org.yard.validator.key.RowLocation;
+import org.yard.validator.util.Logger;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class CheckProducer {
+
+    public static List<Check> getChecks(final ParserResult parse) {
+        final List<Check> result = new ArrayList<>();
+        try {
+            final Set<ColumnKey> bundleKeys = formBundleKeys(parse.getResult());
+            final Map<Integer, RunBundle> bundles = formBundles(parse.getResult(), bundleKeys);
+
+            for (final RunBundle value : bundles.values()) {
+                result.addAll(getCheckList(parse.getHitPolicy(), value.getMap()));
+            }
+
+        } catch (final Exception e) {
+            Logger.log("Failed to create checks: " + e.getMessage());
+        }
+        return result;
+    }
+
+    private static Set<ColumnKey> formBundleKeys(final Map<RowLocation, CustomTreeSet> parse) {
+        final Set<ColumnKey> result = new HashSet<>();
+        for (final CustomTreeSet value : parse.values()) {
+            if (value != null) {
+                if (result.isEmpty()) {
+                    result.addAll(value.getEqualColumns());
+                } else {
+                    final Set<ColumnKey> removeKeys = result.stream().filter(x -> !value.getEqualColumns().contains(x)).collect(Collectors.toSet());
+                    result.removeAll(removeKeys);
+                }
+            }
+        }
+        return result;
+    }
+
+    private static Map<Integer, RunBundle> formBundles(final Map<RowLocation, CustomTreeSet> parse,
+            final Set<ColumnKey> bundleKeys) {
+        final Map<Integer, RunBundle> result = new HashMap<>();
+        for (Map.Entry<RowLocation, CustomTreeSet> entry : parse.entrySet()) {
+            int hash = entry.getValue().getHash(bundleKeys);
+            if (!result.containsKey(hash)) {
+                result.put(hash, new RunBundle());
+            }
+            result.get(hash).put(entry.getKey(), entry.getValue());
+        }
+        return result;
+    }
+
+    private static List<Check> getCheckList(
+            final String hitPolicy,
+            final Map<RowLocation, CustomTreeSet> parse) {
+        final List<Check> result = new ArrayList<>();
+
+        // Dual row
+        int locationIndex = 0;
+        final RowLocation[] locations = new RowLocation[parse.keySet().size()];
+        for (RowLocation location : parse.keySet()) {
+            locations[locationIndex++] = location;
+        }
+
+        for (int i = 0; i < parse.entrySet().size(); i++) {
+            for (int j = i; j < parse.entrySet().size(); j++) {
+                if (i == j) {
+                    continue;
+                }
+                final RowLocation locationA = getHigher(locations, i, j);
+                final RowLocation locationB = getLower(locations, i, j);
+
+                final CheckItem checkItemA = new CheckItem(
+                        locationA.getTableRowNumber(),
+                        locationA,
+                        parse.get(locationA));
+                final CheckItem checkItemB = new CheckItem(
+                        locationB.getTableRowNumber(),
+                        locationB,
+                        parse.get(locationB));
+
+                result.add(new SubsumptionCheck(
+                        hitPolicy,
+                        checkItemA,
+                        checkItemB));
+            }
+        }
+        return result;
+    }
+
+    private static RowLocation getHigher(
+            final RowLocation[] locations,
+            final int i,
+            final int j) {
+        if (locations[i].getTableRowNumber() > locations[j].getTableRowNumber()) {
+            return locations[i];
+        } else {
+            return locations[j];
+        }
+    }
+
+    private static RowLocation getLower(
+            final RowLocation[] locations,
+            final int i,
+            final int j) {
+        if (locations[i].getTableRowNumber() < locations[j].getTableRowNumber()) {
+            return locations[i];
+        } else {
+            return locations[j];
+        }
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/RunBundle.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/RunBundle.java
new file mode 100644
index 0000000000..cb3e852e8f
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/RunBundle.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.checks;
+
+import org.yard.validator.CustomTreeSet;
+import org.yard.validator.key.RowLocation;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RunBundle {
+
+    private final Map<RowLocation, CustomTreeSet> map = new HashMap<>();
+
+    public Map<RowLocation, CustomTreeSet> getMap() {
+        return map;
+    }
+
+    public void put(final RowLocation key,
+                    final CustomTreeSet value) {
+        map.put(key, value);
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/SubsumptionCheck.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/SubsumptionCheck.java
new file mode 100644
index 0000000000..01d2b43e2d
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/checks/SubsumptionCheck.java
@@ -0,0 +1,265 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.checks;
+
+import org.yard.validator.Issue;
+import org.yard.validator.key.Key;
+import org.yard.validator.key.KeyParent;
+import org.yard.validator.key.OperatorValueKey;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import static org.yard.model.Operators.*;
+
+public class SubsumptionCheck
+        implements Check {
+
+    private final String hitPolicy;
+    private final CheckItem checkItemA;
+    private final CheckItem checkItemB;
+
+    public SubsumptionCheck(
+            final String hitPolicy,
+            final CheckItem checkItemA,
+            final CheckItem checkItemB) {
+        this.hitPolicy = hitPolicy;
+        this.checkItemA = checkItemA;
+        this.checkItemB = checkItemB;
+    }
+
+    @Override
+    public Optional<Issue> check() {
+        final Optional<Issue> aToB = getIssue(checkItemA, checkItemB);
+
+        if (isFirstHitPolicy()) {
+            if (aToB.isPresent()) {
+                // No need to check for redundancy. The first row masks the rest.
+                return Optional.of(new Issue(
+                        "Masking row. The higher row prevents the activation of the other row.",
+                        checkItemA.getLocation(),
+                        checkItemB.getLocation()));
+            } else {
+                // No need to check the other row for subsumption,
+                // since subsumption is likely there by rule design
+                return Optional.empty();
+            }
+        } else {
+            final Optional<Issue> bToA = getIssue(checkItemB, checkItemA);
+
+            // If the counterpart in the table is subsumptant, meaning the other item subsumes this, we have redundancy.
+            if (aToB.isPresent() && bToA.isPresent()) {
+                return Optional.of(new Issue(
+                        getRedundancyMessage(),
+                        checkItemA.getLocation(),
+                        checkItemB.getLocation()));
+            } else if (aToB.isPresent()) {
+                return aToB;
+            } else {
+                return bToA;
+            }
+        }
+    }
+
+    private String getRedundancyMessage() {
+        if (Objects.equals("UNIQUE", hitPolicy)) {
+            return "Redundancy found. Unique hit policy fails when more than one row returns results.";
+        } else {
+            return "Redundancy found. If both rows return the same result, the other can be removed. If they return different results, the table fails to return a value.";
+        }
+    }
+
+    private String getSubsumptionMessage() {
+        if (Objects.equals("UNIQUE", hitPolicy)) {
+            return "Subsumption found. Unique hit policy fails when more than one row returns results.";
+        } else {
+            return "Subsumption found. If both rows return the same result, the other can be removed. If they return different results, the table fails to return a value.";
+        }
+    }
+
+    private boolean isFirstHitPolicy() {
+        return Objects.equals("FIRST", hitPolicy)
+                // PRIORITY can not be set since the column header does not support listing it.
+                // For this reason it acts the same way as FIRST
+                || Objects.equals("PRIORITY", hitPolicy);
+    }
+
+    private Optional<Issue> getIssue(
+            final CheckItem checkItemA,
+            final CheckItem checkItemB) {
+        // All values and ranges in A are covered by B
+        int coveredBIndex = 0;
+        for (int aIndex = 0; aIndex < checkItemA.getKeys().length; aIndex++) {
+            final Key key = checkItemA.getKeys()[aIndex];
+            final KeyParent parent = key.getParent();
+
+            for (int bIndex = coveredBIndex; bIndex < checkItemB.getKeys().length; bIndex++) {
+                try {
+                    final Key other = findCounterPartParent(checkItemB, parent, bIndex);
+                    coveredBIndex = bIndex + 1;
+                    if (!subsumes((OperatorValueKey) key, (OperatorValueKey) other)) {
+                        return Optional.empty();
+                    }
+                    break;
+                } catch (NotFoundException e) {
+                    // All good for now, the other has "any" marked for this parent.
+                }
+            }
+        }
+        return Optional.of(
+                new Issue(
+                        getSubsumptionMessage(),
+                        checkItemA.getLocation(),
+                        checkItemB.getLocation()));
+    }
+
+    private Key findCounterPartParent(final CheckItem checkItem,
+            final KeyParent parent,
+            final int i) throws NotFoundException {
+        if (checkItem.getKeys()[i].getParent().equals(parent)) {
+            return checkItem.getKeys()[i];
+        }
+        throw new NotFoundException();
+    }
+
+    public boolean subsumes(final OperatorValueKey keyA,
+            final OperatorValueKey keyB) {
+        switch (keyA.getOperator()) {
+            case NOT_EQUALS:
+                switch (keyB.getOperator()) {
+                    case NOT_EQUALS:
+                        return valueIsEqualTo(keyA.getValue(), keyB.getValue());
+                    case EQUALS:
+                        boolean valueIsEqualTo = valueIsEqualTo(keyA.getValue(), keyB.getValue());
+                        boolean covers = covers(keyA, keyB.getValue());
+                        return !valueIsEqualTo && !covers;
+                    default:
+                        return false;
+                }
+            case EQUALS:
+                switch (keyB.getOperator()) {
+                    case NOT_EQUALS:
+                        boolean valueIsEqualTo = valueIsEqualTo(keyA.getValue(), keyB.getValue());
+                        boolean covers = covers(keyA, keyB.getValue());
+                        return !valueIsEqualTo && !covers;
+                    default:
+                        return covers(keyA, keyB.getValue());
+                }
+            case GREATER_OR_EQUAL:
+                switch (keyB.getOperator()) {
+                    case GREATER_OR_EQUAL:
+                    case GREATER_THAN:
+                        return covers(keyA, keyB.getValue());
+                    case NOT_EQUALS:
+                        return valueIsGreaterThan(keyA, keyB.getValue());
+                    default:
+                        return false;
+                }
+
+            case LESS_OR_EQUAL:
+                switch (keyB.getOperator()) {
+                    case LESS_OR_EQUAL:
+                    case LESS_THAN:
+                        return covers(keyA, keyB.getValue());
+                    case NOT_EQUALS:
+                        return valueIsLessThan(keyA, keyB.getValue());
+                    default:
+                        return false;
+                }
+            case LESS_THAN:
+                switch (keyB.getOperator()) {
+                    case LESS_OR_EQUAL:
+                        return covers(keyA, keyB.getValue());
+                    case LESS_THAN:
+                    case NOT_EQUALS:
+                        return valueIsLessThanOrEqualTo(keyA, keyB.getValue());
+                    default:
+                        return false;
+                }
+            case GREATER_THAN:
+                switch (keyB.getOperator()) {
+                    case GREATER_OR_EQUAL:
+                        return covers(keyA, keyB.getValue());
+                    case GREATER_THAN:
+                    case NOT_EQUALS:
+                        return valueIsGreaterThanOrEqualTo(keyA, keyB.getValue());
+                    default:
+                        return false;
+                }
+            default:
+                return false;
+        }
+    }
+
+    protected boolean valueIsEqualTo(final Comparable valueA,
+            final Comparable valueB) {
+        if (valueA == null) {
+            return valueB == null;
+        } else {
+            if (valueB == null) {
+                return false;
+            } else {
+                return valueA.compareTo(valueB) == 0;
+            }
+        }
+    }
+
+    public boolean covers(final OperatorValueKey key,
+            final Comparable otherValue) {
+        switch (key.getOperator()) {
+            case EQUALS:
+                return valueIsEqualTo(key.getValue(), otherValue);
+            case NOT_EQUALS:
+                return !valueIsEqualTo(key.getValue(), otherValue);
+            case GREATER_OR_EQUAL:
+                return valueIsGreaterThanOrEqualTo(key, otherValue);
+            case LESS_OR_EQUAL:
+                return valueIsLessThanOrEqualTo(key, otherValue);
+            case LESS_THAN:
+                return valueIsLessThan(key, otherValue);
+            case GREATER_THAN:
+                return valueIsGreaterThan(key, otherValue);
+            default:
+                return false;
+        }
+    }
+
+    protected boolean valueIsGreaterThanOrEqualTo(final OperatorValueKey key,
+            final Comparable otherValue) {
+        return valueIsEqualTo(key.getValue(), otherValue) || valueIsGreaterThan(key, otherValue);
+    }
+
+    protected boolean valueIsLessThanOrEqualTo(final OperatorValueKey key,
+            final Comparable otherValue) {
+        return valueIsEqualTo(key.getValue(), otherValue) || valueIsLessThan(key, otherValue);
+    }
+
+    protected boolean valueIsGreaterThan(final OperatorValueKey key,
+            final Comparable otherValue) {
+        return otherValue.compareTo(key.getValue()) > 0;
+    }
+
+    protected boolean valueIsLessThan(final OperatorValueKey key,
+            final Comparable otherValue) {
+        return otherValue.compareTo(key.getValue()) < 0;
+    }
+
+    private class NotFoundException extends Throwable {
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/ColumnKey.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/ColumnKey.java
new file mode 100644
index 0000000000..dadc536d26
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/ColumnKey.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+
+import java.util.Objects;
+
+public class ColumnKey implements KeyParent, Comparable<KeyParent> {
+
+    private final String column;
+
+    public ColumnKey(final String column) {
+        this.column = column;
+    }
+
+    @Override
+    public String toString() {
+        return column;
+    }
+
+    @Override
+    public int compareTo(final KeyParent o) {
+        if (o instanceof ColumnKey) {
+            return column.compareTo(((ColumnKey) o).column);
+        } else {
+            return -1;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ColumnKey columnKey = (ColumnKey) o;
+        return Objects.equals(column, columnKey.column);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(column);
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/Key.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/Key.java
new file mode 100644
index 0000000000..20f6aae98d
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/Key.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+/**
+ * The key, path down to field in DRL or DMN case.
+ */
+public interface Key {
+
+    Location getLocation();
+
+    KeyParent getParent();
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/KeyImpl.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/KeyImpl.java
new file mode 100644
index 0000000000..ad473f9002
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/KeyImpl.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+public class KeyImpl implements Key {
+
+    protected final Location location;
+    protected final KeyParent parent;
+
+    public KeyImpl(final Location location,
+                   final KeyParent parent) {
+        this.location = location;
+        this.parent = parent;
+    }
+
+    @Override
+    public Location getLocation() {
+        return location;
+    }
+
+    @Override
+    public KeyParent getParent() {
+        return parent;
+    }
+
+    @Override
+    public String toString() {
+        return parent.toString();
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/KeyParent.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/KeyParent.java
new file mode 100644
index 0000000000..c30e707fce
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/KeyParent.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+/**
+ * Parent of the key. Everything leading to pattern for example:
+ *
+ * rule-activation-group-from-pattern
+ */
+public interface KeyParent {
+
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/Location.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/Location.java
new file mode 100644
index 0000000000..447a4257d8
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/Location.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+/**
+ * Used to group keys and track the location of use.
+ */
+public interface Location<T>
+        extends Comparable<T>{
+
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/ObjectKey.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/ObjectKey.java
new file mode 100644
index 0000000000..9accc50ac1
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/ObjectKey.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+
+import org.yard.model.Operators;
+
+public class ObjectKey extends OperatorValueKey {
+
+    public ObjectKey(final Location location,
+                     final KeyParent parent,
+                     final Comparable value) {
+        super(location,
+                parent,
+                Operators.EQUALS,
+                value);
+    }
+
+    @Override
+    public String toString() {
+        return parent + " " + value;
+    }
+
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/OperatorValueKey.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/OperatorValueKey.java
new file mode 100644
index 0000000000..cbc27d3b8f
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/OperatorValueKey.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+
+public class OperatorValueKey extends KeyImpl {
+
+    private final String operator;
+    protected final Comparable value;
+
+    public OperatorValueKey(final Location location,
+                            final KeyParent parent,
+                            final String operator,
+                            final Comparable value) {
+        super(location,
+             parent );
+        this.operator = operator;
+        this.value = value;
+    }
+
+    public String getOperator() {
+        return operator;
+    }
+
+    public Comparable getValue() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return parent + " " + operator + " " + value;
+    }
+
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/key/RowLocation.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/RowLocation.java
new file mode 100644
index 0000000000..0baafe539e
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/key/RowLocation.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.key;
+
+public class RowLocation implements Location<RowLocation> {
+
+    private final int actualRowNumberInFile;
+    final int tableRowNumber;
+
+    public RowLocation(final int tableRowNumber,
+            final int actualRowNumberInFile) {
+        this.tableRowNumber = tableRowNumber;
+        this.actualRowNumberInFile = actualRowNumberInFile;
+    }
+
+    public int getActualRowNumberInFile() {
+        return actualRowNumberInFile;
+    }
+
+    public int getTableRowNumber() {
+        return tableRowNumber;
+    }
+
+    @Override
+    public String toString() {
+        return "Table row " + tableRowNumber + " actual row " + actualRowNumberInFile;
+    }
+
+    @Override
+    public int compareTo(final RowLocation o) {
+        return Integer.compare(tableRowNumber, o.tableRowNumber);
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/runner/Runner.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/runner/Runner.java
new file mode 100644
index 0000000000..0f45e3839f
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/runner/Runner.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.runner;
+
+import org.yard.validator.Issue;
+import org.yard.validator.ReportBus;
+import org.yard.validator.checks.Check;
+import org.yard.validator.util.Logger;
+
+import java.util.List;
+import java.util.Optional;
+
+public class Runner {
+
+    private ReportBus reportBus;
+
+    public Runner(ReportBus reportBus) {
+        this.reportBus = reportBus;
+    }
+
+    public void run(final List<Check> checks) {
+        try {
+
+            for (final Check check : checks) {
+                final Optional<Issue> issue = check.check();
+                issue.ifPresent(value -> reportBus.report(value));
+            }
+        } catch (final Exception e) {
+            Logger.log("Failed to run checks: " + e.getMessage());
+        }
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Callback.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Callback.java
new file mode 100644
index 0000000000..02d6bc51a3
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Callback.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.util;
+
+import jsinterop.annotations.JsFunction;
+
+@JsFunction
+public interface Callback {
+    void callback(final String s);
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Date.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Date.java
new file mode 100644
index 0000000000..71ef822971
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Date.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.util;
+
+/**
+ * Our own custom Date.
+ * We do not need all the features normal date has, just the ability to compare.
+ * This brings less trouble and dependencies for the J2CL.
+ */
+public class Date implements Comparable {
+
+    private final String value;
+    private final int years;
+    private final int months;
+    private final int days;
+
+
+    public Date(final String value) {
+        this.value = value;
+
+        final String[] split = value.split("-");
+        // Format yyyy-MM-dd
+        try {
+            years = Integer.parseInt(split[0]);
+            months = Integer.parseInt(split[1]);
+            days = Integer.parseInt(split[2]);
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        if (o instanceof Date) {
+            final Date other = (Date) o;
+            final int compareYears = Integer.compare(years, other.years);
+            if (compareYears == 0) {
+                final int compareMonths = Integer.compare(months, other.months);
+                if (compareMonths == 0) {
+                    return Integer.compare(days, other.days);
+                } else {
+                    return compareMonths;
+                }
+            } else {
+                return compareYears;
+            }
+        } else {
+            return -1;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return value;
+    }
+}
diff --git a/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Logger.java b/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Logger.java
new file mode 100644
index 0000000000..16c2945192
--- /dev/null
+++ b/packages/yard-validator-worker/src/main/java/org/yard/validator/util/Logger.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class Logger {
+
+    private static final Collection<Callback> callbacks = new ArrayList<>();
+
+    public static void startLogging(final Callback callback) {
+        Logger.callbacks.add(callback);
+    }
+
+    public static void log(final String s) {
+        for (Callback callback : callbacks) {
+            callback.callback(getTime() + " " + s);
+        }
+    }
+
+    private static String getTime() {
+        return System.currentTimeMillis() + "";
+    }
+}
diff --git a/packages/yard-validator-worker/src/test/java/org/yard/validator/ParserTest.java b/packages/yard-validator-worker/src/test/java/org/yard/validator/ParserTest.java
new file mode 100644
index 0000000000..f608ca6456
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/java/org/yard/validator/ParserTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+
+import org.junit.Test;
+import org.yard.validator.key.Key;
+import org.yard.validator.key.Location;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Map;
+import java.util.Scanner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ParserTest {
+
+    @Test
+    public void inlineRuleTest() throws IOException {
+        final String read = read("traffic-violation.yml");
+        final ParserResult parse = new Parser().parse(read);
+
+
+        for (Location location : parse.getResult().keySet()) {
+            System.out.println(location);
+
+            for (Key key : parse.getResult().get(location).toArray(new Key[parse.getResult().get(location).size()])) {
+                System.out.println(key);
+            }
+        }
+        assertEquals(4, parse.getResult().keySet().size());
+    }
+
+    @Test
+    public void whenThenRuleTest() throws IOException {
+        final String read = read("service-price.yml");
+        final ParserResult parse = new Parser().parse(read);
+
+
+        for (Location location : parse.getResult().keySet()) {
+            System.out.println(location);
+            for (Key key : parse.getResult().get(location).toArray(new Key[parse.getResult().get(location).size()])) {
+                System.out.println(key);
+            }
+        }
+        assertEquals(4, parse.getResult().keySet().size());
+    }
+
+    private String read(final String name) throws FileNotFoundException {
+        final StringBuffer buffer = new StringBuffer();
+
+        final URL resource = ParserTest.class.getResource(name);
+
+        final Scanner sc = new Scanner(new File(resource.getFile()));
+
+        while (sc.hasNextLine()) {
+            buffer.append(sc.nextLine());
+            buffer.append(System.lineSeparator());
+        }
+
+        return buffer.toString();
+    }
+
+}
\ No newline at end of file
diff --git a/packages/yard-validator-worker/src/test/java/org/yard/validator/YardValidatorTest.java b/packages/yard-validator-worker/src/test/java/org/yard/validator/YardValidatorTest.java
new file mode 100644
index 0000000000..6a8b259349
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/java/org/yard/validator/YardValidatorTest.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator;
+
+import org.junit.Test;
+import org.yard.validator.key.Location;
+import org.yard.validator.key.RowLocation;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.util.*;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class YardValidatorTest {
+
+    @Test
+    public void subsumption() throws FileNotFoundException {
+        final String read = read("subsumption.yml");
+        final YardValidator validator = new YardValidator();
+
+        final List<Issue> issues = new ArrayList<>();
+
+        validator.validate(read, issues::add);
+
+        for (Issue issue : issues) {
+            System.out.println(issue.getMessage());
+        }
+
+        assertEquals(1, issues.size());
+        assertIssue(issues.get(0), "Subsumption found. If both rows return the same result, the other can be removed. If they return different results, the table fails to return a value.", 2, 3);
+
+    }
+
+    @Test
+    public void subsumptionTheOtherWay() throws FileNotFoundException {
+        final String read = read("subsumption-the-other-way.yml");
+        final YardValidator validator = new YardValidator();
+
+        final List<Issue> issues = new ArrayList<>();
+
+        validator.validate(read, issues::add);
+
+        for (Issue issue : issues) {
+            System.out.println(issue.getMessage());
+        }
+
+        assertEquals(1, issues.size());
+        assertIssue(issues.get(0), "Subsumption found. If both rows return the same result, the other can be removed. If they return different results, the table fails to return a value.", 2, 3);
+
+    }
+
+    @Test
+    public void maskingRule() throws FileNotFoundException {
+        final String read = read("subsumption-the-other-way.yml", "First");
+        final YardValidator validator = new YardValidator();
+
+        final List<Issue> issues = new ArrayList<>();
+
+        validator.validate(read, issues::add);
+
+        assertEquals(1, issues.size());
+        assertIssue(issues.get(0), "Masking row. The higher row prevents the activation of the other row.", 2, 3);
+    }
+
+    @Test
+    public void redundancy() throws FileNotFoundException {
+        final String read = read("redundancy.yml");
+        final YardValidator validator = new YardValidator();
+
+        final List<Issue> issues = new ArrayList<>();
+
+        validator.validate(read, issues::add);
+
+        for (Issue issue : issues) {
+            System.out.println(issue.getMessage());
+        }
+
+        assertEquals(1, issues.size());
+        assertIssue(issues.get(0), "Redundancy found. If both rows return the same result, the other can be removed. If they return different results, the table fails to return a value.", 1, 2);
+    }
+
+    @Test
+    public void redundancyWithUniqueHP() throws FileNotFoundException {
+        final String read = read("redundancy.yml", "Unique");
+        final YardValidator validator = new YardValidator();
+
+        final List<Issue> issues = new ArrayList<>();
+
+        validator.validate(read, issues::add);
+
+        for (Issue issue : issues) {
+            System.out.println(issue.getMessage());
+        }
+
+        assertEquals(1, issues.size());
+        assertIssue(issues.get(0), "Redundancy found. Unique hit policy fails when more than one row returns results.", 1, 2);
+    }
+    private void assertIssue(
+            final Issue issue,
+            final String message,
+            final Integer... wantedRows) {
+        final List<Integer> rows = Arrays.asList(wantedRows);
+        assertEquals(message, issue.getMessage());
+
+        for (Location location : issue.getLocations()) {
+            System.out.println(location);
+        }
+
+        assertEquals(issue.getLocations().length, rows.size());
+        for (Location location : issue.getLocations()) {
+            if (location instanceof RowLocation) {
+                assertTrue(rows.contains(((RowLocation) location).getTableRowNumber()));
+            }
+        }
+    }
+
+    private String read(final String name) throws FileNotFoundException {
+        return read(name, null);
+    }
+
+    private String read(
+            final String name,
+            final String hitPolicy) throws FileNotFoundException {
+        final StringBuilder buffer = new StringBuilder();
+
+        final URL resource = ParserTest.class.getResource(name);
+
+        final Scanner sc = new Scanner(new File(resource.getFile()));
+
+        while (sc.hasNextLine()) {
+            final String line = sc.nextLine();
+            buffer.append(line);
+            buffer.append(System.lineSeparator());
+            if (hitPolicy != null && line.trim().startsWith("outputComponents")) {
+                buffer.append("      hitPolicy: ").append(hitPolicy);
+                buffer.append(System.lineSeparator());
+            }
+        }
+
+        return buffer.toString();
+    }
+}
\ No newline at end of file
diff --git a/packages/yard-validator-worker/src/test/java/org/yard/validator/util/DateTest.java b/packages/yard-validator-worker/src/test/java/org/yard/validator/util/DateTest.java
new file mode 100644
index 0000000000..8e86722dc4
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/java/org/yard/validator/util/DateTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.yard.validator.util;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class DateTest {
+
+    private final String givenDateA;
+    private final String givenDateB;
+    private final int expectedNumber;
+
+    public DateTest(final String givenDateA,
+                    final String givenDateB,
+                    final int expectedNumber) {
+
+        this.givenDateA = givenDateA;
+        this.givenDateB = givenDateB;
+        this.expectedNumber = expectedNumber;
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][]{
+                {"2000-10-30", "2000-10-30", 0},
+                {"2000-10-30", "2000-10-31", -1},
+                {"2000-10-31", "2000-10-30", 1},
+                {"2000-10-30", "2000-11-30", -1},
+                {"2000-11-30", "2000-10-30", 1},
+                {"2000-10-30", "2001-10-30", -1},
+                {"2001-10-30", "2000-10-30", 1}
+        });
+    }
+
+    @Test
+    public void test() {
+        assertEquals(expectedNumber,
+                new Date(givenDateA).compareTo(
+                        new Date(givenDateB)));
+
+    }
+}
\ No newline at end of file
diff --git a/packages/yard-validator-worker/src/test/resources/org/yard/validator/redundancy.yml b/packages/yard-validator-worker/src/test/resources/org/yard/validator/redundancy.yml
new file mode 100644
index 0000000000..ac98c5e21b
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/resources/org/yard/validator/redundancy.yml
@@ -0,0 +1,26 @@
+specVersion: alpha
+kind: YaRD
+name: "Traffic Violation"
+expressionLang: alpha
+inputs:
+  - name: "Driver"
+    type: "http://myapi.org/jsonSchema.json#Driver"
+  - name: "Violation"
+    type: "http://myapi.org/jsonSchema.json#Violation"
+elements:
+  - name: "Fine"
+    type: Decision
+    requirements: ["Violation"]
+    logic:
+      type: DecisionTable
+      inputs: ["Violation.type", "Violation.Actual Speed - Violation.Speed Limit"]
+      outputComponents: ["Amount", "Points"]
+      rules:
+        - ['="speed"', "[10..30)", 500, 3]
+        - ['="speed"', "[10..30)", 500, 3]
+  - name: "Should the driver be suspended?"
+    type: Decision
+    requirements: ["Driver", "Fine"]
+    logic:
+      type: LiteralExpression
+      expression: 'if Driver.Points + Fine.Points >= 20 then "Yes" else "No"'
diff --git a/packages/yard-validator-worker/src/test/resources/org/yard/validator/service-price.yml b/packages/yard-validator-worker/src/test/resources/org/yard/validator/service-price.yml
new file mode 100644
index 0000000000..bd00ac3d73
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/resources/org/yard/validator/service-price.yml
@@ -0,0 +1,24 @@
+specVersion: alpha
+kind: YaRD
+name: "BasePrice"
+expressionLang: alpha
+inputs:
+  - name: "Age"
+    type: date
+  - name: "Previous incidents?"
+    type: boolean
+elements:
+  - name: "Base price"
+    type: Decision
+    logic:
+      type: DecisionTable
+      inputs: ["Age", "Previous incidents?"]
+      rules:
+        - when: ["<2017-09-07", false]
+          then: 800
+        - when: ["<2017-09-07", true]
+          then: 1000
+        - when: [">=2017-09-07", false]
+          then: 500
+        - when: [">=2017-09-07", true]
+          then: 650
diff --git a/packages/yard-validator-worker/src/test/resources/org/yard/validator/subsumption-the-other-way.yml b/packages/yard-validator-worker/src/test/resources/org/yard/validator/subsumption-the-other-way.yml
new file mode 100644
index 0000000000..38edae6a80
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/resources/org/yard/validator/subsumption-the-other-way.yml
@@ -0,0 +1,29 @@
+specVersion: alpha
+kind: YaRD
+name: "Traffic Violation"
+expressionLang: alpha
+inputs:
+  - name: "Driver"
+    type: "http://myapi.org/jsonSchema.json#Driver"
+  - name: "Violation"
+    type: "http://myapi.org/jsonSchema.json#Violation"
+elements:
+  - name: "Fine"
+    type: Decision
+    requirements: ["Violation"]
+    logic:
+      type: DecisionTable
+      inputs: ["Violation.type", "Violation.Actual Speed - Violation.Speed Limit"]
+      outputComponents: ["Amount", "Points"]
+      rules:
+        - ['="speed"', "[10..30)", 500, 3]
+        - ['="speed"', ">= 60", 1000, 7]
+        - ['="speed"', ">= 30", 1000, 7]
+        - ['="parking"', "-", 100, 1]
+        - ['="driving under the influence"', "-", 1000, 5]
+  - name: "Should the driver be suspended?"
+    type: Decision
+    requirements: ["Driver", "Fine"]
+    logic:
+      type: LiteralExpression
+      expression: 'if Driver.Points + Fine.Points >= 20 then "Yes" else "No"'
diff --git a/packages/yard-validator-worker/src/test/resources/org/yard/validator/subsumption.yml b/packages/yard-validator-worker/src/test/resources/org/yard/validator/subsumption.yml
new file mode 100644
index 0000000000..0eb20657f7
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/resources/org/yard/validator/subsumption.yml
@@ -0,0 +1,29 @@
+specVersion: alpha
+kind: YaRD
+name: "Traffic Violation"
+expressionLang: alpha
+inputs:
+  - name: "Driver"
+    type: "http://myapi.org/jsonSchema.json#Driver"
+  - name: "Violation"
+    type: "http://myapi.org/jsonSchema.json#Violation"
+elements:
+  - name: "Fine"
+    type: Decision
+    requirements: ["Violation"]
+    logic:
+      type: DecisionTable
+      inputs: ["Violation.type", "Violation.Actual Speed - Violation.Speed Limit"]
+      outputComponents: ["Amount", "Points"]
+      rules:
+        - ['="speed"', "[10..30)", 500, 3]
+        - ['="speed"', ">= 30", 1000, 7]
+        - ['="speed"', ">= 60", 1000, 7]
+        - ['="parking"', "-", 100, 1]
+        - ['="driving under the influence"', "-", 1000, 5]
+  - name: "Should the driver be suspended?"
+    type: Decision
+    requirements: ["Driver", "Fine"]
+    logic:
+      type: LiteralExpression
+      expression: 'if Driver.Points + Fine.Points >= 20 then "Yes" else "No"'
diff --git a/packages/yard-validator-worker/src/test/resources/org/yard/validator/traffic-violation-empty-row.yml b/packages/yard-validator-worker/src/test/resources/org/yard/validator/traffic-violation-empty-row.yml
new file mode 100644
index 0000000000..0eb20657f7
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/resources/org/yard/validator/traffic-violation-empty-row.yml
@@ -0,0 +1,29 @@
+specVersion: alpha
+kind: YaRD
+name: "Traffic Violation"
+expressionLang: alpha
+inputs:
+  - name: "Driver"
+    type: "http://myapi.org/jsonSchema.json#Driver"
+  - name: "Violation"
+    type: "http://myapi.org/jsonSchema.json#Violation"
+elements:
+  - name: "Fine"
+    type: Decision
+    requirements: ["Violation"]
+    logic:
+      type: DecisionTable
+      inputs: ["Violation.type", "Violation.Actual Speed - Violation.Speed Limit"]
+      outputComponents: ["Amount", "Points"]
+      rules:
+        - ['="speed"', "[10..30)", 500, 3]
+        - ['="speed"', ">= 30", 1000, 7]
+        - ['="speed"', ">= 60", 1000, 7]
+        - ['="parking"', "-", 100, 1]
+        - ['="driving under the influence"', "-", 1000, 5]
+  - name: "Should the driver be suspended?"
+    type: Decision
+    requirements: ["Driver", "Fine"]
+    logic:
+      type: LiteralExpression
+      expression: 'if Driver.Points + Fine.Points >= 20 then "Yes" else "No"'
diff --git a/packages/yard-validator-worker/src/test/resources/org/yard/validator/traffic-violation.yml b/packages/yard-validator-worker/src/test/resources/org/yard/validator/traffic-violation.yml
new file mode 100644
index 0000000000..452ff7505f
--- /dev/null
+++ b/packages/yard-validator-worker/src/test/resources/org/yard/validator/traffic-violation.yml
@@ -0,0 +1,28 @@
+specVersion: alpha
+kind: YaRD
+name: "Traffic Violation"
+expressionLang: alpha
+inputs:
+  - name: "Driver"
+    type: "http://myapi.org/jsonSchema.json#Driver"
+  - name: "Violation"
+    type: "http://myapi.org/jsonSchema.json#Violation"
+elements:
+  - name: "Fine"
+    type: Decision
+    requirements: ["Violation"]
+    logic:
+      type: DecisionTable
+      inputs: ["Violation.type", "Violation.Actual Speed - Violation.Speed Limit"]
+      outputComponents: ["Amount", "Points"]
+      rules:
+        - ['="speed"', "[10..30)", 500, 3]
+        - ['="speed"', ">= 30", 1000, 7]
+        - ['="parking"', "-", 100, 1]
+        - ['="driving under the influence"', "-", 1000, 5]
+  - name: "Should the driver be suspended?"
+    type: Decision
+    requirements: ["Driver", "Fine"]
+    logic:
+      type: LiteralExpression
+      expression: 'if Driver.Points + Fine.Points >= 20 then "Yes" else "No"'
diff --git a/packages/yard-validator/README.md b/packages/yard-validator/README.md
new file mode 100644
index 0000000000..5ecc889f2c
--- /dev/null
+++ b/packages/yard-validator/README.md
@@ -0,0 +1,8 @@
+## YARD validator
+
+###### Module for YARD (Yet Another Rule Definition) validation.
+
+### When used in an editor
+
+The TypeScript source provides methods for getting the reporting as VSCode compatible Notifications.
+The webworker file needs to be included separately.
diff --git a/packages/yard-validator/env/index.js b/packages/yard-validator/env/index.js
new file mode 100644
index 0000000000..26e1811bd5
--- /dev/null
+++ b/packages/yard-validator/env/index.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+const { varsWithName, composeEnv } = require("@kie-tools-scripts/build-env");
+
+module.exports = composeEnv([require("@kie-tools/root-env/env")], {
+  vars: varsWithName({}),
+  get env() {
+    return {
+      yardValidator: {
+        version: require("../package.json").version,
+      },
+    };
+  },
+});
diff --git a/packages/yard-validator/install.js b/packages/yard-validator/install.js
new file mode 100644
index 0000000000..4247286a3f
--- /dev/null
+++ b/packages/yard-validator/install.js
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+const buildEnv = require("./env");
+const { setup } = require("@kie-tools/maven-config-setup-helper");
+
+setup(`
+    -Drevision=${buildEnv.env.yardValidator.version}
+`);
diff --git a/packages/yard-validator/package.json b/packages/yard-validator/package.json
new file mode 100644
index 0000000000..fb1bc88f4e
--- /dev/null
+++ b/packages/yard-validator/package.json
@@ -0,0 +1,44 @@
+{
+  "private": false,
+  "name": "@kie-tools/yard-validator",
+  "version": "0.0.0",
+  "description": "",
+  "license": "Apache-2.0",
+  "keywords": [],
+  "homepage": "https://github.com/kiegroup/kie-tools",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/kiegroup/kie-tools.git"
+  },
+  "bugs": {
+    "url": "https://github.com/kiegroup/kie-tools/issues"
+  },
+  "scripts": {
+    "build:dev": "rimraf dist && tsc -p tsconfig.json && pnpm copy:webworker",
+    "build:prod": "pnpm lint && tsc -p tsconfig.json && pnpm copy:webworker",
+    "copy:webworker": "copyfiles -f node_modules/@kie-tools/yard-validator-worker/dist/yard-validator-worker.js dist",
+    "install": "node install.js",
+    "install:mvnw": "run-script-os",
+    "lint": "echo 'Linting'",
+    "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command"
+  },
+  "dependencies": {
+    "@kie-tools-core/notifications": "workspace:*",
+    "@kie-tools/yard-validator-worker": "workspace:*"
+  },
+  "devDependencies": {
+    "@kie-tools/maven-config-setup-helper": "workspace:*",
+    "@kie-tools/root-env": "workspace:*",
+    "@kie-tools/tsconfig": "workspace:*",
+    "copyfiles": "^2.4.1",
+    "rimraf": "^3.0.2",
+    "run-script-os": "^1.1.6",
+    "typescript": "^4.6.2"
+  },
+  "kieTools": {
+    "requiredPreinstalledCliCommands": [
+      "java",
+      "mvn"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/packages/yard-validator/src/ValidationResult.ts b/packages/yard-validator/src/ValidationResult.ts
new file mode 100644
index 0000000000..41ad01fb62
--- /dev/null
+++ b/packages/yard-validator/src/ValidationResult.ts
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+export interface ValidationResult {
+  log: string[];
+  result: Result[];
+}
+
+export interface Result {
+  issue: string;
+  locations: Location[];
+}
+
+export interface Location {
+  rowInFile: number;
+  rowInTable: number;
+}
diff --git a/packages/yard-validator/src/index.ts b/packages/yard-validator/src/index.ts
new file mode 100644
index 0000000000..6e2da143b3
--- /dev/null
+++ b/packages/yard-validator/src/index.ts
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+export * from "./main";
diff --git a/packages/yard-validator/src/main.ts b/packages/yard-validator/src/main.ts
new file mode 100644
index 0000000000..58c9fbccf6
--- /dev/null
+++ b/packages/yard-validator/src/main.ts
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+import { Notification } from "@kie-tools-core/notifications/dist/api";
+import { ValidationResult } from "./ValidationResult";
+
+export function validationPromise(yaml: String): Promise<Notification[]> {
+  return new Promise((resolve, reject) => {
+    const worker = new Worker("/yard-validator-worker.js");
+    worker.postMessage(yaml);
+    worker.onmessage = (e) => {
+      const notifications: Notification[] = [];
+
+      try {
+        const validationResult: ValidationResult = JSON.parse(e.data);
+
+        for (const result of validationResult.result) {
+          for (const location of result.locations) {
+            notifications.push({
+              path: "",
+              severity: "ERROR",
+              message: result.issue,
+              type: "PROBLEM",
+              position: {
+                startLineNumber: location.rowInFile,
+                startColumn: 0,
+                endLineNumber: 0,
+                endColumn: 0,
+              },
+            });
+          }
+        }
+      } catch (e) {
+        // We add nothing since json is malformed.
+      }
+      resolve(notifications);
+      worker.terminate();
+    };
+  });
+}
diff --git a/packages/yard-validator/tsconfig.json b/packages/yard-validator/tsconfig.json
new file mode 100644
index 0000000000..253b1749aa
--- /dev/null
+++ b/packages/yard-validator/tsconfig.json
@@ -0,0 +1,9 @@
+{
+  "extends": "@kie-tools/tsconfig/tsconfig.json",
+  "compilerOptions": {
+    "outDir": "dist",
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true
+  },
+  "include": ["./src"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 893f9a55b2..28193d2b2b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5421,7 +5421,7 @@ importers:
         version: 4.8.4
       url-loader:
         specifier: ^4.1.1
-        version: 4.1.1(webpack@5.88.2)
+        version: 4.1.1(file-loader@6.2.0)(webpack@5.88.2)
       webpack:
         specifier: ^5.88.2
         version: 5.88.2(webpack-cli@4.10.0)
@@ -5834,7 +5834,7 @@ importers:
         version: 4.1.1(file-loader@6.2.0)(webpack@5.88.2)
       webpack:
         specifier: ^5.88.2
-        version: 5.88.2
+        version: 5.88.2(webpack-cli@4.10.0)
 
   packages/playwright-base:
     devDependencies:
@@ -6851,6 +6851,9 @@ importers:
       "@kie-tools/yard-language-service":
         specifier: workspace:*
         version: link:../yard-language-service
+      "@kie-tools/yard-validator":
+        specifier: workspace:*
+        version: link:../yard-validator
       "@octokit/plugin-rest-endpoint-methods":
         specifier: ^5.0.1
         version: 5.0.1(@octokit/core@3.4.0)
@@ -8655,10 +8658,10 @@ importers:
         version: 4.8.4
       webpack:
         specifier: ^5.88.2
-        version: 5.88.2
+        version: 5.88.2(webpack-cli@4.10.0)
       webpack-dev-server:
         specifier: ^4.15.1
-        version: 4.15.1(webpack@5.88.2)
+        version: 4.15.1(webpack-cli@4.10.0)(webpack@5.88.2)
       webpack-merge:
         specifier: ^5.9.0
         version: 5.9.0
@@ -9541,7 +9544,7 @@ importers:
         version: 9.4.2(typescript@4.8.4)(webpack@5.88.2)
       webpack:
         specifier: ^5.88.2
-        version: 5.88.2
+        version: 5.88.2(webpack-cli@4.10.0)
 
   packages/workspace:
     dependencies:
@@ -9894,6 +9897,9 @@ importers:
       "@kie-tools/yard-language-service":
         specifier: workspace:*
         version: link:../yard-language-service
+      "@kie-tools/yard-validator":
+        specifier: workspace:*
+        version: link:../yard-validator
       "@patternfly/react-core":
         specifier: ^4.276.6
         version: 4.276.6(react-dom@17.0.2)(react@17.0.2)
@@ -10086,6 +10092,96 @@ importers:
         specifier: ^4.6.2
         version: 4.8.4
 
+  packages/yard-model:
+    dependencies:
+      "@kie-tools-core/notifications":
+        specifier: workspace:*
+        version: link:../notifications
+    devDependencies:
+      "@kie-tools/maven-config-setup-helper":
+        specifier: workspace:*
+        version: link:../maven-config-setup-helper
+      "@kie-tools/root-env":
+        specifier: workspace:*
+        version: link:../root-env
+      copy-webpack-plugin:
+        specifier: ^11.0.0
+        version: 11.0.0(webpack@5.88.2)
+      rimraf:
+        specifier: ^3.0.2
+        version: 3.0.2
+      run-script-os:
+        specifier: ^1.1.6
+        version: 1.1.6
+      typescript:
+        specifier: ^4.6.2
+        version: 4.8.4
+      webpack:
+        specifier: ^5.88.2
+        version: 5.88.2(webpack-cli@4.10.0)
+
+  packages/yard-validator:
+    dependencies:
+      "@kie-tools-core/notifications":
+        specifier: workspace:*
+        version: link:../notifications
+      "@kie-tools/yard-validator-worker":
+        specifier: workspace:*
+        version: link:../yard-validator-worker
+    devDependencies:
+      "@kie-tools/maven-config-setup-helper":
+        specifier: workspace:*
+        version: link:../maven-config-setup-helper
+      "@kie-tools/root-env":
+        specifier: workspace:*
+        version: link:../root-env
+      "@kie-tools/tsconfig":
+        specifier: workspace:*
+        version: link:../tsconfig
+      copyfiles:
+        specifier: ^2.4.1
+        version: 2.4.1
+      rimraf:
+        specifier: ^3.0.2
+        version: 3.0.2
+      run-script-os:
+        specifier: ^1.1.6
+        version: 1.1.6
+      typescript:
+        specifier: ^4.6.2
+        version: 4.8.4
+
+  packages/yard-validator-worker:
+    dependencies:
+      "@kie-tools-core/notifications":
+        specifier: workspace:*
+        version: link:../notifications
+      "@kie-tools/yard-model":
+        specifier: workspace:*
+        version: link:../yard-model
+    devDependencies:
+      "@kie-tools/maven-config-setup-helper":
+        specifier: workspace:*
+        version: link:../maven-config-setup-helper
+      "@kie-tools/root-env":
+        specifier: workspace:*
+        version: link:../root-env
+      "@kie-tools/tsconfig":
+        specifier: workspace:*
+        version: link:../tsconfig
+      copyfiles:
+        specifier: ^2.4.1
+        version: 2.4.1
+      rimraf:
+        specifier: ^3.0.2
+        version: 3.0.2
+      run-script-os:
+        specifier: ^1.1.6
+        version: 1.1.6
+      typescript:
+        specifier: ^4.6.2
+        version: 4.8.4
+
   packages/yard-vscode-extension:
     dependencies:
       "@kie-tools-core/backend":
@@ -11092,7 +11188,7 @@ packages:
       "@babel/compat-data": 7.21.7
       "@babel/core": 7.16.12
       "@babel/helper-validator-option": 7.21.0
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       semver: 6.3.1
     dev: true
 
@@ -11106,7 +11202,7 @@ packages:
       "@babel/compat-data": 7.21.7
       "@babel/core": 7.23.0
       "@babel/helper-validator-option": 7.21.0
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       semver: 6.3.1
     dev: true
 
@@ -11120,7 +11216,7 @@ packages:
       "@babel/compat-data": 7.21.7
       "@babel/core": 7.16.12
       "@babel/helper-validator-option": 7.21.0
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       lru-cache: 5.1.1
       semver: 6.3.1
     dev: true
@@ -11135,7 +11231,7 @@ packages:
       "@babel/compat-data": 7.21.7
       "@babel/core": 7.18.10
       "@babel/helper-validator-option": 7.21.0
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       lru-cache: 5.1.1
       semver: 6.3.1
     dev: true
@@ -11150,7 +11246,7 @@ packages:
       "@babel/compat-data": 7.21.7
       "@babel/core": 7.23.0
       "@babel/helper-validator-option": 7.21.0
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       lru-cache: 5.1.1
       semver: 6.3.1
     dev: true
@@ -23878,15 +23974,6 @@ packages:
       acorn: 8.10.0
     dev: true
 
-  /acorn-import-assertions@1.9.0(acorn@8.8.2):
-    resolution:
-      { integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== }
-    peerDependencies:
-      acorn: ^8
-    dependencies:
-      acorn: 8.8.2
-    dev: true
-
   /acorn-jsx@5.3.2(acorn@7.4.1):
     resolution:
       { integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== }
@@ -24733,8 +24820,8 @@ packages:
     peerDependencies:
       postcss: ^8.1.0
     dependencies:
-      browserslist: 4.21.5
-      caniuse-lite: 1.0.30001486
+      browserslist: 4.22.1
+      caniuse-lite: 1.0.30001547
       fraction.js: 4.2.0
       normalize-range: 0.1.2
       picocolors: 1.0.0
@@ -25491,10 +25578,10 @@ packages:
     engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 }
     hasBin: true
     dependencies:
-      caniuse-lite: 1.0.30001332
-      electron-to-chromium: 1.4.107
+      caniuse-lite: 1.0.30001547
+      electron-to-chromium: 1.4.549
       escalade: 3.1.1
-      node-releases: 2.0.3
+      node-releases: 2.0.13
       picocolors: 1.0.0
     dev: true
 
@@ -25504,10 +25591,10 @@ packages:
     engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 }
     hasBin: true
     dependencies:
-      caniuse-lite: 1.0.30001486
-      electron-to-chromium: 1.4.388
-      node-releases: 2.0.10
-      update-browserslist-db: 1.0.11(browserslist@4.21.5)
+      caniuse-lite: 1.0.30001547
+      electron-to-chromium: 1.4.549
+      node-releases: 2.0.13
+      update-browserslist-db: 1.0.13(browserslist@4.21.5)
     dev: true
 
   /browserslist@4.22.1:
@@ -25856,16 +25943,6 @@ packages:
       path-temp: 2.0.0
     dev: true
 
-  /caniuse-lite@1.0.30001332:
-    resolution:
-      { integrity: sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw== }
-    dev: true
-
-  /caniuse-lite@1.0.30001486:
-    resolution:
-      { integrity: sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg== }
-    dev: true
-
   /caniuse-lite@1.0.30001547:
     resolution:
       { integrity: sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA== }
@@ -26672,7 +26749,7 @@ packages:
       globby: 13.1.2
       normalize-path: 3.0.0
       schema-utils: 4.0.0
-      serialize-javascript: 6.0.0
+      serialize-javascript: 6.0.1
       webpack: 5.76.1(esbuild@0.15.5)
     dev: true
 
@@ -26688,7 +26765,7 @@ packages:
       globby: 13.1.2
       normalize-path: 3.0.0
       schema-utils: 4.0.0
-      serialize-javascript: 6.0.0
+      serialize-javascript: 6.0.1
       webpack: 5.88.2(webpack-cli@4.10.0)
     dev: true
 
@@ -26709,7 +26786,7 @@ packages:
     resolution:
       { integrity: sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== }
     dependencies:
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       semver: 7.0.0
     dev: true
 
@@ -26717,7 +26794,7 @@ packages:
     resolution:
       { integrity: sha512-nriW1nuJjUgvkEjIot1Spwakz52V9YkYHZAQG6A1eCgC8AA1p0zngrQEP9R0+V6hji5XilWKG1Bd0YRppmGimA== }
     dependencies:
-      browserslist: 4.21.5
+      browserslist: 4.22.1
     dev: true
 
   /core-js-compat@3.33.0:
@@ -28257,16 +28334,6 @@ packages:
       jake: 10.8.7
     dev: true
 
-  /electron-to-chromium@1.4.107:
-    resolution:
-      { integrity: sha512-Huen6taaVrUrSy8o7mGStByba8PfOWWluHNxSHGBrCgEdFVLtvdQDBr9LBCF9Uci8SYxh28QNNMO0oC17wbGAg== }
-    dev: true
-
-  /electron-to-chromium@1.4.388:
-    resolution:
-      { integrity: sha512-xZ0y4zjWZgp65okzwwt00f2rYibkFPHUv9qBz+Vzn8cB9UXIo9Zc6Dw81LJYhhNt0G/vR1OJEfStZ49NKl0YxQ== }
-    dev: true
-
   /electron-to-chromium@1.4.549:
     resolution:
       { integrity: sha512-gpXfJslSi4hYDkA0mTLEpYKRv9siAgSUgZ+UWyk+J5Cttpd1ThCVwdclzIwQSclz3hYn049+M2fgrP1WpvF8xg== }
@@ -28408,7 +28475,7 @@ packages:
     engines: { node: ">=10.13.0" }
     dependencies:
       graceful-fs: 4.2.11
-      tapable: 2.2.0
+      tapable: 2.2.1
     dev: true
 
   /enhanced-resolve@5.9.3:
@@ -28417,7 +28484,7 @@ packages:
     engines: { node: ">=10.13.0" }
     dependencies:
       graceful-fs: 4.2.11
-      tapable: 2.2.0
+      tapable: 2.2.1
     dev: true
 
   /enquirer@2.3.6:
@@ -30035,7 +30102,7 @@ packages:
       is-glob: 4.0.3
       normalize-path: 3.0.0
       schema-utils: 4.0.0
-      webpack: 5.88.2
+      webpack: 5.88.2(webpack-cli@4.10.0)
     dev: true
 
   /filename-reserved-regex@2.0.0:
@@ -31418,7 +31485,7 @@ packages:
       html-minifier-terser: 6.1.0
       lodash: 4.17.21
       pretty-error: 4.0.0
-      tapable: 2.2.0
+      tapable: 2.2.1
       webpack: 5.88.2(@swc/core@1.3.92)(esbuild@0.18.20)(webpack-cli@4.10.0)
     dev: true
 
@@ -33965,7 +34032,7 @@ packages:
     dependencies:
       glob: 7.2.0
       minimatch: 3.0.5
-      webpack: 5.88.2
+      webpack: 5.88.2(webpack-cli@4.10.0)
       webpack-merge: 4.2.2
     dev: true
 
@@ -35869,21 +35936,11 @@ packages:
       webpack: 5.88.2(webpack-cli@4.10.0)
     dev: true
 
-  /node-releases@2.0.10:
-    resolution:
-      { integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== }
-    dev: true
-
   /node-releases@2.0.13:
     resolution:
       { integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== }
     dev: true
 
-  /node-releases@2.0.3:
-    resolution:
-      { integrity: sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw== }
-    dev: true
-
   /node.extend@2.0.2:
     resolution:
       { integrity: sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ== }
@@ -37608,7 +37665,7 @@ packages:
       "@csstools/postcss-trigonometric-functions": 1.0.2(postcss@8.4.16)
       "@csstools/postcss-unset-value": 1.0.2(postcss@8.4.16)
       autoprefixer: 10.4.14(postcss@8.4.16)
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       css-blank-pseudo: 3.0.3(postcss@8.4.16)
       css-has-pseudo: 3.0.4(postcss@8.4.16)
       css-prefers-color-scheme: 6.0.3(postcss@8.4.16)
@@ -39797,7 +39854,7 @@ packages:
       klona: 2.0.5
       neo-async: 2.6.2
       sass: 1.49.9
-      webpack: 5.88.2
+      webpack: 5.88.2(webpack-cli@4.10.0)
     dev: true
 
   /sass-loader@13.0.2(sass@1.54.4)(webpack@5.76.1):
@@ -40502,7 +40559,7 @@ packages:
       abab: 2.0.5
       iconv-lite: 0.6.3
       source-map-js: 0.6.2
-      webpack: 5.88.2
+      webpack: 5.88.2(webpack-cli@4.10.0)
     dev: true
 
   /source-map-loader@4.0.0(webpack@5.76.1):
@@ -42386,9 +42443,9 @@ packages:
       setimmediate: 1.0.5
     dev: true
 
-  /update-browserslist-db@1.0.11(browserslist@4.21.5):
+  /update-browserslist-db@1.0.13(browserslist@4.21.5):
     resolution:
-      { integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== }
+      { integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== }
     hasBin: true
     peerDependencies:
       browserslist: ">= 4.21.0"
@@ -42458,23 +42515,6 @@ packages:
         optional: true
     dependencies:
       file-loader: 6.2.0(webpack@5.88.2)
-      loader-utils: 2.0.2
-      mime-types: 2.1.34
-      schema-utils: 3.1.1
-      webpack: 5.88.2
-    dev: true
-
-  /url-loader@4.1.1(webpack@5.88.2):
-    resolution:
-      { integrity: sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== }
-    engines: { node: ">= 10.13.0" }
-    peerDependencies:
-      file-loader: "*"
-      webpack: ^4.0.0 || ^5.0.0
-    peerDependenciesMeta:
-      file-loader:
-        optional: true
-    dependencies:
       loader-utils: 2.0.2
       mime-types: 2.1.34
       schema-utils: 3.1.1
@@ -43481,58 +43521,6 @@ packages:
       - utf-8-validate
     dev: true
 
-  /webpack-dev-server@4.15.1(webpack@5.88.2):
-    resolution:
-      { integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA== }
-    engines: { node: ">= 12.13.0" }
-    hasBin: true
-    peerDependencies:
-      webpack: ^4.37.0 || ^5.0.0
-      webpack-cli: "*"
-    peerDependenciesMeta:
-      webpack:
-        optional: true
-      webpack-cli:
-        optional: true
-    dependencies:
-      "@types/bonjour": 3.5.10
-      "@types/connect-history-api-fallback": 1.3.5
-      "@types/express": 4.17.17
-      "@types/serve-index": 1.9.1
-      "@types/serve-static": 1.13.10
-      "@types/sockjs": 0.3.33
-      "@types/ws": 8.5.5
-      ansi-html-community: 0.0.8
-      bonjour-service: 1.1.1
-      chokidar: 3.5.3
-      colorette: 2.0.16
-      compression: 1.7.4
-      connect-history-api-fallback: 2.0.0
-      default-gateway: 6.0.3
-      express: 4.18.2
-      graceful-fs: 4.2.11
-      html-entities: 2.3.2
-      http-proxy-middleware: 2.0.6(@types/express@4.17.17)
-      ipaddr.js: 2.0.1
-      launch-editor: 2.6.0
-      open: 8.4.0
-      p-retry: 4.6.1
-      rimraf: 3.0.2
-      schema-utils: 4.0.0
-      selfsigned: 2.1.1
-      serve-index: 1.9.1
-      sockjs: 0.3.24
-      spdy: 4.0.2
-      webpack: 5.88.2
-      webpack-dev-middleware: 5.3.3(webpack@5.88.2)
-      ws: 8.13.0
-    transitivePeerDependencies:
-      - bufferutil
-      - debug
-      - supports-color
-      - utf-8-validate
-    dev: true
-
   /webpack-hot-middleware@2.25.4:
     resolution:
       { integrity: sha512-IRmTspuHM06aZh98OhBJtqLpeWFM8FXJS5UYpKYxCJzyFoyWj1w6VGFfomZU7OPA55dMLrQK0pRT1eQ3PACr4w== }
@@ -43617,7 +43605,7 @@ packages:
       "@webassemblyjs/wasm-parser": 1.11.1
       acorn: 8.10.0
       acorn-import-assertions: 1.9.0(acorn@8.10.0)
-      browserslist: 4.21.5
+      browserslist: 4.22.1
       chrome-trace-event: 1.0.2
       enhanced-resolve: 5.15.0
       es-module-lexer: 0.9.3
@@ -43630,7 +43618,7 @@ packages:
       mime-types: 2.1.34
       neo-async: 2.6.2
       schema-utils: 3.3.0
-      tapable: 2.2.0
+      tapable: 2.2.1
       terser-webpack-plugin: 5.3.9(esbuild@0.15.5)(webpack@5.76.1)
       watchpack: 2.4.0
       webpack-sources: 3.2.3
@@ -43640,47 +43628,6 @@ packages:
       - uglify-js
     dev: true
 
-  /webpack@5.88.2:
-    resolution:
-      { integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== }
-    engines: { node: ">=10.13.0" }
-    hasBin: true
-    peerDependencies:
-      webpack-cli: "*"
-    peerDependenciesMeta:
-      webpack-cli:
-        optional: true
-    dependencies:
-      "@types/eslint-scope": 3.7.3
-      "@types/estree": 1.0.1
-      "@webassemblyjs/ast": 1.11.6
-      "@webassemblyjs/wasm-edit": 1.11.6
-      "@webassemblyjs/wasm-parser": 1.11.6
-      acorn: 8.10.0
-      acorn-import-assertions: 1.9.0(acorn@8.10.0)
-      browserslist: 4.21.5
-      chrome-trace-event: 1.0.2
-      enhanced-resolve: 5.15.0
-      es-module-lexer: 1.3.0
-      eslint-scope: 5.1.1
-      events: 3.3.0
-      glob-to-regexp: 0.4.1
-      graceful-fs: 4.2.11
-      json-parse-even-better-errors: 2.3.1
-      loader-runner: 4.2.0
-      mime-types: 2.1.34
-      neo-async: 2.6.2
-      schema-utils: 3.3.0
-      tapable: 2.2.0
-      terser-webpack-plugin: 5.3.9(webpack@5.88.2)
-      watchpack: 2.4.0
-      webpack-sources: 3.2.3
-    transitivePeerDependencies:
-      - "@swc/core"
-      - esbuild
-      - uglify-js
-    dev: true
-
   /webpack@5.88.2(@swc/core@1.3.92)(esbuild@0.18.20)(webpack-cli@4.10.0):
     resolution:
       { integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== }
@@ -43739,8 +43686,8 @@ packages:
       "@webassemblyjs/ast": 1.11.6
       "@webassemblyjs/wasm-edit": 1.11.6
       "@webassemblyjs/wasm-parser": 1.11.6
-      acorn: 8.8.2
-      acorn-import-assertions: 1.9.0(acorn@8.8.2)
+      acorn: 8.10.0
+      acorn-import-assertions: 1.9.0(acorn@8.10.0)
       browserslist: 4.21.5
       chrome-trace-event: 1.0.2
       enhanced-resolve: 5.15.0
@@ -44248,12 +44195,12 @@ packages:
     resolution:
       { integrity: sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== }
     engines: { node: ">=10" }
+    dev: true
 
   /yargs-parser@20.2.9:
     resolution:
       { integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== }
     engines: { node: ">=10" }
-    dev: true
 
   /yargs-parser@21.0.0:
     resolution:
@@ -44300,7 +44247,7 @@ packages:
       require-directory: 2.1.1
       string-width: 4.2.3
       y18n: 5.0.8
-      yargs-parser: 20.2.7
+      yargs-parser: 20.2.9
 
   /yargs@17.3.1:
     resolution:
diff --git a/repo/graph.dot b/repo/graph.dot
index 96fc6b4494..0f74d57881 100644
--- a/repo/graph.dot
+++ b/repo/graph.dot
@@ -146,6 +146,9 @@ digraph G {
   "vscode-extension-kogito-bundle" [ color = "blue", fontcolor = "blue", style = "rounded" ];
   "@kie-tools/xml-parser-ts" [ color = "blue", fontcolor = "blue", style = "rounded" ];
   "@kie-tools/yard-language-service" [ color = "blue", fontcolor = "blue", style = "rounded" ];
+  "@kie-tools/yard-validator" [ color = "blue", fontcolor = "blue", style = "rounded" ];
+  "@kie-tools/yard-model" [ color = "blue", fontcolor = "blue", style = "rounded" ];
+  "@kie-tools/yard-validator-worker" [ color = "blue", fontcolor = "blue", style = "rounded" ];
   "yard-vscode-extension" [ color = "blue", fontcolor = "blue", style = "rounded" ];
   "@kie-tools-scripts/build-env" [ color = "blue", fontcolor = "blue", style = "rounded" ];
   "kie-tools-root" -> "@kie-tools-scripts/bootstrap" [ style = "dashed", color = "black" ];
@@ -479,8 +482,13 @@ digraph G {
   "@kie-tools/yard-editor" -> "@kie-tools-core/editor" [ style = "solid", color = "blue" ];
   "@kie-tools/yard-editor" -> "@kie-tools/i18n-common-dictionary" [ style = "solid", color = "blue" ];
   "@kie-tools/yard-editor" -> "@kie-tools/yard-language-service" [ style = "solid", color = "blue" ];
+  "@kie-tools/yard-editor" -> "@kie-tools/yard-validator" [ style = "solid", color = "blue" ];
   "@kie-tools/yard-editor" -> "@kie-tools-core/webpack-base" [ style = "dashed", color = "blue" ];
   "@kie-tools/yard-language-service" -> "@kie-tools/json-yaml-language-service" [ style = "solid", color = "blue" ];
+  "@kie-tools/yard-model" -> "@kie-tools-core/notifications" [ style = "solid", color = "blue" ];
+  "@kie-tools/yard-model" -> "@kie-tools/maven-config-setup-helper" [ style = "dashed", color = "blue" ];
+  "@kie-tools/yard-validator" -> "@kie-tools/yard-validator-worker" [ style = "solid", color = "blue" ];
+  "@kie-tools/yard-validator-worker" -> "@kie-tools/yard-model" [ style = "solid", color = "blue" ];
   "yard-vscode-extension" -> "@kie-tools-core/vscode-extension" [ style = "solid", color = "blue" ];
   "yard-vscode-extension" -> "@kie-tools/yard-editor" [ style = "solid", color = "blue" ];
   "yard-vscode-extension" -> "@kie-tools/vscode-extension-common-test-helpers" [ style = "dashed", color = "blue" ];
diff --git a/repo/graph.json b/repo/graph.json
index a58c636554..9a107df4ae 100644
--- a/repo/graph.json
+++ b/repo/graph.json
@@ -133,6 +133,7 @@
       { "id": "@kie-tools/serverless-logic-web-tools-swf-builder-image-env" },
       { "id": "@kie-tools/serverless-logic-web-tools-swf-dev-mode-image-env" },
       { "id": "@kie-tools/yard-language-service" },
+      { "id": "@kie-tools/yard-validator" },
       { "id": "@kie-tools/serverless-logic-web-tools-base-builder-image" },
       { "id": "@kie-tools/serverless-logic-web-tools-swf-builder-image" },
       { "id": "sonataflow-deployment-webapp" },
@@ -146,6 +147,8 @@
       { "id": "vscode-extension-dashbuilder-editor" },
       { "id": "vscode-extension-kie-ba-bundle" },
       { "id": "vscode-extension-kogito-bundle" },
+      { "id": "@kie-tools/yard-validator-worker" },
+      { "id": "@kie-tools/yard-model" },
       { "id": "yard-vscode-extension" }
     ],
     "links": [
@@ -783,6 +786,7 @@
       { "source": "@kie-tools/yard-editor", "target": "@kie-tools-core/editor", "weight": 1 },
       { "source": "@kie-tools/yard-editor", "target": "@kie-tools/i18n-common-dictionary", "weight": 1 },
       { "source": "@kie-tools/yard-editor", "target": "@kie-tools/yard-language-service", "weight": 1 },
+      { "source": "@kie-tools/yard-editor", "target": "@kie-tools/yard-validator", "weight": 1 },
       { "source": "@kie-tools/yard-editor", "target": "@kie-tools-core/webpack-base", "weight": 1 },
       {
         "source": "@kie-tools/serverless-logic-web-tools-base-builder-image-env",
@@ -800,6 +804,7 @@
         "weight": 1
       },
       { "source": "@kie-tools/yard-language-service", "target": "@kie-tools/json-yaml-language-service", "weight": 1 },
+      { "source": "@kie-tools/yard-validator", "target": "@kie-tools/yard-validator-worker", "weight": 1 },
       {
         "source": "@kie-tools/serverless-logic-web-tools-base-builder-image",
         "target": "@kie-tools/serverless-logic-web-tools-base-builder-image-env",
@@ -899,6 +904,9 @@
       { "source": "vscode-extension-kogito-bundle", "target": "@kie-tools-core/webpack-base", "weight": 1 },
       { "source": "vscode-extension-kogito-bundle", "target": "@kie-tools/eslint", "weight": 1 },
       { "source": "vscode-extension-kogito-bundle", "target": "@kie-tools/tsconfig", "weight": 1 },
+      { "source": "@kie-tools/yard-validator-worker", "target": "@kie-tools/yard-model", "weight": 1 },
+      { "source": "@kie-tools/yard-model", "target": "@kie-tools-core/notifications", "weight": 1 },
+      { "source": "@kie-tools/yard-model", "target": "@kie-tools/maven-config-setup-helper", "weight": 1 },
       { "source": "yard-vscode-extension", "target": "@kie-tools-core/vscode-extension", "weight": 1 },
       { "source": "yard-vscode-extension", "target": "@kie-tools/yard-editor", "weight": 1 },
       { "source": "yard-vscode-extension", "target": "@kie-tools/vscode-extension-common-test-helpers", "weight": 1 }
@@ -1068,6 +1076,9 @@
     ["@kie-tools/yaml-language-server", "packages/yaml-language-server"],
     ["@kie-tools/yard-editor", "packages/yard-editor"],
     ["@kie-tools/yard-language-service", "packages/yard-language-service"],
+    ["@kie-tools/yard-model", "packages/yard-model"],
+    ["@kie-tools/yard-validator", "packages/yard-validator"],
+    ["@kie-tools/yard-validator-worker", "packages/yard-validator-worker"],
     ["yard-vscode-extension", "packages/yard-vscode-extension"],
     ["@kie-tools-scripts/bootstrap", "scripts/bootstrap"],
     ["@kie-tools-scripts/build-env", "scripts/build-env"],


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org