diff --git a/.eslintrc b/.eslintrc
index f767226..6426667 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -37,6 +37,8 @@
     "no-array-constructor": "off",
     "@typescript-eslint/no-array-constructor": ["error"],
 
+    "no-useless-constructor": "off",
+
     // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/keyword-spacing.md
     "keyword-spacing": "off",
     "@typescript-eslint/keyword-spacing": ["error"],
@@ -47,7 +49,12 @@
     "@typescript-eslint/explicit-function-return-type": "error",
 
     // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-explicit-any.md
-    "@typescript-eslint/no-explicit-any": "error",
+    "@typescript-eslint/no-explicit-any": [
+      "error",
+      {
+        "ignoreRestArgs": true
+      }
+    ],
 
     // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md
     "@typescript-eslint/no-non-null-assertion": "error",
diff --git a/.github/workflows/Code Quality.yml b/.github/workflows/Code Quality.yml
index 4c73bd6..ba050e1 100644
--- a/.github/workflows/Code Quality.yml	
+++ b/.github/workflows/Code Quality.yml	
@@ -1,32 +1,50 @@
 name: Code Quality
 
-on: [push, pull_request]
+on: [push]
 
 jobs:
-  Prettier:
-    name: Prettier
-    strategy:
-      matrix:
-        os: ['ubuntu-latest']
-        node: ['14.x']
-    runs-on: ${{ matrix.os }}
-    steps:
-      - uses: actions/checkout@v2.3.4
-      - uses: actions/setup-node@v2.1.4
-        with:
-          node-version: ${{ matrix.node }}
-          registry-url: 'https://registry.npmjs.org'
-      - name: Install dependencies
-        run: npm ci
-      - name: Run Prettier
-        run: npm run prettier
+  # Prettier:
+  #   name: Prettier
+  #   strategy:
+  #     matrix:
+  #       os: ['ubuntu-latest']
+  #       node: ['14.x']
+  #   runs-on: ${{ matrix.os }}
+  #   steps:
+  #     - uses: actions/checkout@v2.3.4
+  #     - uses: actions/setup-node@v2.1.4
+  #       with:
+  #         node-version: ${{ matrix.node }}
+  #         registry-url: 'https://registry.npmjs.org'
+  #     - name: Install dependencies
+  #       run: npm ci
+  #     - name: Run Prettier
+  #       run: npm run prettier
+
+  # ESLint:
+  #   name: ESLint
+  #   strategy:
+  #     matrix:
+  #       os: ['ubuntu-latest']
+  #       node: ['14.x']
+  #   runs-on: ${{ matrix.os }}
+  #   steps:
+  #     - uses: actions/checkout@v2.3.4
+  #     - uses: actions/setup-node@v2.1.4
+  #       with:
+  #         node-version: ${{ matrix.node }}
+  #         registry-url: 'https://registry.npmjs.org'
+  #     - name: Install dependencies
+  #       run: npm ci
+  #     - name: Run ESLint
+  #       run: npm run lint
 
-  ESLint:
-    name: ESLint
+  Check:
+    name: IPAM Checker
     strategy:
       matrix:
         os: ['ubuntu-latest']
-        node: ['14.x']
+        node: ['15.x']
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v2.3.4
@@ -36,5 +54,7 @@ jobs:
           registry-url: 'https://registry.npmjs.org'
       - name: Install dependencies
         run: npm ci
-      - name: Run ESLint
-        run: npm run lint
+      - name: Setup Matcher
+        run: echo "::add-matcher::./schemas/problem-matcher.json"
+      - name: Run IPAM Checker
+        run: npm run runBin runActions.ts
diff --git a/.github/workflows/Push.yml b/.github/workflows/Push.yml
index 5cd228c..8235792 100644
--- a/.github/workflows/Push.yml
+++ b/.github/workflows/Push.yml
@@ -8,7 +8,7 @@ jobs:
     strategy:
       matrix:
         os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
-        node: ['14.x']
+        node: ['15.x']
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v2.3.4
diff --git a/.releaserc b/.releaserc
new file mode 100644
index 0000000..1727745
--- /dev/null
+++ b/.releaserc
@@ -0,0 +1,32 @@
+{
+  "plugins": [
+    [
+      "@semantic-release/commit-analyzer",
+      {
+        "preset": "conventionalcommits"
+      }
+    ],
+    "@semantic-release/release-notes-generator",
+    [
+      "@semantic-release/changelog",
+      {
+        "changelogFile": "docs/CHANGELOG.md"
+      }
+    ],
+    "@semantic-release/npm",
+    [
+      "@semantic-release/git",
+      {
+        "assets": [
+          "docs/CHANGELOG.md",
+          "package.json",
+          "package-lock.json"
+        ]
+      }
+    ],
+    "@semantic-release/github"
+  ],
+  "branches": [
+    "master"
+  ]
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 105d3ef..d379942 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,6 +10,9 @@
       "restart": true,
 
       "cwd": "${workspaceFolder}",
+      "env": {
+        "LOG_MODE": "DEBUG"
+      },
       "runtimeExecutable": "npx",
       "runtimeArgs": ["nodemon"]
     }
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 485d2ea..306a385 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,6 +1,15 @@
 {
   "typescript.tsdk": "node_modules/typescript/lib",
   "yaml.schemas": {
-    "/workspace/schemas/IPAM.json": ["ipam.yml", "ipam.yaml", "IPAM.yaml", "IPAM.yml", "**/fixtures/*.yml", "**/fixtures/*.yaml"]
+    "/workspace/schemas/IPAM.json": [
+      "ipam.yml",
+      "ipam.yaml",
+      "IPAM.yaml",
+      "IPAM.yml",
+      "**/fixtures/*.yml",
+      "**/fixtures/*.yaml",
+      "IPAM-Test.yaml",
+      "Playground/*.yaml"
+    ]
   }
-}
\ No newline at end of file
+}
diff --git a/IPAM-Test.yaml b/IPAM-Test.yaml
new file mode 100644
index 0000000..6a83d42
--- /dev/null
+++ b/IPAM-Test.yaml
@@ -0,0 +1,54 @@
+communities:
+  - name: Toronto
+    id: tor
+    contactId: tor.todo1
+    sites:
+      - id: tor.c1
+        name: Toronto Cabniet 12
+        devices:
+          - id: tor.c1.rt1
+            name: Torotno Cabinet 1 Router 1
+
+      - id: tor.c2
+        name: Toronto Cabniet 2
+        devices:
+          - id: tor.c2.rt1
+            name: Torotno Cabinet 2 Router 1
+
+circuits:
+  - id: tor.clink
+    sideAID: tor.c1
+    sideZID: tor.c2
+    speed: 10G
+
+circuitLocations:
+  - id: tor.c1
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+  - id: tor.c2
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+contacts:
+  - id: tor.todo1
+    name: TODO
+
+networks:
+  - prefix: 1.0.0.0/23
+    networks:
+      - prefix: 1.0.0.0/30
+        hosts:
+          - ip: 1.0.0.1
+            description: Toronto Cabniet 1
+            contactId: tor.todo1
+            deviceId: tor.c1.rt1
+            deviceInterface: TenGigE0/0/0/1
+          - ip: 1.0.0.2
+            description: Toronto Cabniet 2
+            deviceId: tor.c2.rt1
+            deviceInterface: TenGigE0/0/0/2
diff --git a/Playground/Devices.yaml b/Playground/Devices.yaml
new file mode 100644
index 0000000..c8c1a5e
--- /dev/null
+++ b/Playground/Devices.yaml
@@ -0,0 +1,56 @@
+communities:
+  - name: Toronto
+    id: tor
+    contactId: tor.todo1
+    sites:
+      - id: tor.c1
+        name: Toronto Cabniet 12
+        devices:
+        - id: tor.c1.rt1
+          name: Torotno Cabinet 1 Router 1
+
+      - id: tor.c2
+        name: Toronto Cabniet 2
+        devices:
+        - id: tor.c2.rt1
+          name: Torotno Cabinet 2 Router 1
+
+circuits:
+  - id: tor.clink
+    sideA:
+      id: tor.c1
+    sideZ:
+      id: tor.c2
+    speed: 10G
+
+circuitLocations:
+  - id: tor.c1
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+  - id: tor.c2
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+contacts:
+  - id: tor.todo1
+    name: TODO
+
+networks:
+  - prefix: 1.0.0.0/23
+    networks:
+      - prefix: 1.0.0.0/30
+        hosts:
+          - ip: 1.0.0.1
+            description: Toronto Cabniet 1
+            contactId: tor.todo1
+            deviceId: tor.c1.rt0
+            deviceInterface: TenGigE0/0/0/1
+          - ip: 1.0.0.2
+            description: Toronto Cabniet 2
+            deviceId: tor.c2.rt1
+            deviceInterface: TenGigE0/0/0/2
\ No newline at end of file
diff --git a/Playground/README.md b/Playground/README.md
new file mode 100644
index 0000000..8625d94
--- /dev/null
+++ b/Playground/README.md
@@ -0,0 +1,15 @@
+# Replacements
+
+Replace devices.id & devices.interface with `deviceInterface` & `
+
+Search
+
+```
+device:\n\s+id: (\S+)$\n\s\s((.*)(?=interface).*(?<=interface: )(\S+))
+```
+
+Replace
+
+```
+deviceId: $1\n$3deviceInterface: $4
+```
diff --git a/README.md b/README.md
index b0c4b91..aa6e367 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,20 @@
 # KristianFJones/TS-AutoNetwork
 
-TODO
+This is a module created for the ISP I work at [K-Net](https://github.com/knetca), it's a custom build [IP Address Management (IPAM)](https://en.wikipedia.org/wiki/IP_address_management) system that is stored as a [YAML](https://en.wikipedia.org/wiki/YAML#:~:text=YAML%20(a%20recursive%20acronym%20for,is%20being%20stored%20or%20transmitted.) file as is intended to be the root source of truth for all network related services and new automation systems.
+
+## IPAM YAML File
+
+The IPAM YAML defines the following arrays
+
+- Communities each site within a community, and the devices at each site.
+
+- Circuits the unique ID for referencing within network prefixes, the sideA and sizeZ include the ID which is a refernce to a "circuitLocation", and the speed of the "EVC"
+
+- Circuit Locations which is what "circuit providers" think of as the circuit, which includes the circuit provider, the circuit ID that is referenced in "circuits", the address that is provided to the circuit provider, the phyiscal demarc speed.
+
+- Networks, which has a prefix or "network", and can optionally have: a circuit id reference attached, a nsServer array contianing the authoritive nsServers for forwarding reverse DNS, contactId referencing a contact, or children networks.
+
+- Contacts, which are currently unused, but will contain the name, email, and contact information for staff and for automated systems such as processing abuse emails.
 
 ## Usage
 
@@ -19,15 +33,15 @@ Follow these steps to open this project in a container:
 2. To use this repository, you can either open the repository in an isolated Docker volume:
 
    - Press F1 and select the **Remote-Containers: Open Repository in Container...** command.
-   - Enter `K-FOSS/TS-Core-Template`
+   - Enter `KristianFJones/TS-AutoNetwork`
    - The VS Code window (instance) will reload, clone the source code, and start building the dev container. A progress notification provides status updates.
 
    Or open a locally cloned copy of the code:
 
    - Clone this repository to your local filesystem.
-     - `git clone https://github.com/K-FOSS/TS-Core-Template.git`
+     - `git clone https://github.com/KristianFJones/TS-AutoNetwork.git`
    - Open the project folder in Visual Studio Code.
-     - `code ./TS-Core-Template`
+     - `code ./TS-AutoNetwork`
    - Reopen in Container
 
      - When you open the project folder in Visual Studio Code you should be prompted with a notification asking if you would like to reopen in container.
diff --git a/demo/.vscode/extensions.json b/demo/.vscode/extensions.json
deleted file mode 100644
index 36ad0d8..0000000
--- a/demo/.vscode/extensions.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "recommendations": ["esbenp.prettier-vscode", "redhat.vscode-yaml"]
-}
\ No newline at end of file
diff --git a/demo/.vscode/settings.json b/demo/.vscode/settings.json
deleted file mode 100644
index 5161d4f..0000000
--- a/demo/.vscode/settings.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "yaml.schemas": {
-    "https://raw.githubusercontent.com/KristianFJones/TS-AutoNetwork/master/schemas/IPAM.json": ["IPAM.yaml", "ipam.yaml", "ipam.yml", "IPAM.yml"]
-  }
-}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 52292cb..7d119ee 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,19 +1,22 @@
 {
-  "name": "ts-autonetworks",
+  "name": "@k-net/ts-autonetwork",
   "version": "0.0.1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
-      "name": "ts-autonetworks",
+      "name": "@k-net/ts-autonetwork",
       "version": "0.0.1",
       "license": "MIT",
       "dependencies": {
         "@k-foss/ts-esnode": "^1.7.0",
         "ajv": "^7.0.3",
         "bullmq": "^1.14.0",
+        "class-transformer": "^0.3.1",
+        "class-transformer-validator": "^0.9.1",
+        "class-validator": "^0.12.2",
+        "class-validator-jsonschema": "^2.1.1",
         "fast-xml-parser": "^3.17.6",
-        "fluent-json-schema": "^2.0.3",
         "got": "^11.8.1",
         "ip-address": "^7.1.0",
         "js-yaml": "^3.14.1",
@@ -907,6 +910,11 @@
       "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
       "dev": true
     },
+    "node_modules/@types/validator": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.0.0.tgz",
+      "integrity": "sha512-WAy5txG7aFX8Vw3sloEKp5p/t/Xt8jD3GRD9DacnFv6Vo8ubudAsRTXgxpQwU0mpzY/H8U4db3roDuCMjShBmw=="
+    },
     "node_modules/@typescript-eslint/eslint-plugin": {
       "version": "4.13.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.13.0.tgz",
@@ -1768,6 +1776,51 @@
       "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
       "dev": true
     },
+    "node_modules/class-transformer": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.1.tgz",
+      "integrity": "sha512-cKFwohpJbuMovS8xVLmn8N2AUbAuc8pVo4zEfsUVo8qgECOogns1WVk/FkOZoxhOPTyTYFckuoH+13FO+MQ8GA=="
+    },
+    "node_modules/class-transformer-validator": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/class-transformer-validator/-/class-transformer-validator-0.9.1.tgz",
+      "integrity": "sha512-83/KFCyd6UiiwH6PlQS5y17O5TTx58CawvNI+XdrMs0Ig9QI5kiuzRqGcC/WrEpd1F7i4KIxCwdn6m4B6fl0jw==",
+      "peerDependencies": {
+        "class-transformer": ">=0.2.3",
+        "class-validator": ">=0.12.0"
+      }
+    },
+    "node_modules/class-validator": {
+      "version": "0.12.2",
+      "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.12.2.tgz",
+      "integrity": "sha512-TDzPzp8BmpsbPhQpccB3jMUE/3pK0TyqamrK0kcx+ZeFytMA+O6q87JZZGObHHnoo9GM8vl/JppIyKWeEA/EVw==",
+      "dependencies": {
+        "@types/validator": "13.0.0",
+        "google-libphonenumber": "^3.2.8",
+        "tslib": ">=1.9.0",
+        "validator": "13.0.0"
+      }
+    },
+    "node_modules/class-validator-jsonschema": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/class-validator-jsonschema/-/class-validator-jsonschema-2.1.1.tgz",
+      "integrity": "sha512-h9ZjaFgrtk7shrSbYGii08ow+mcrKVjzdBWZ/iHfrro6APOiTxYLTIASBneOfy+8uShocCsvBB2VtBFj8P/+Lg==",
+      "dependencies": {
+        "lodash": "^4.17.20",
+        "openapi3-ts": "^2.0.0",
+        "reflect-metadata": "^0.1.13",
+        "tslib": "^2.0.3"
+      },
+      "peerDependencies": {
+        "class-transformer": "0.2.3 - 0.3.1",
+        "class-validator": "^0.12.0"
+      }
+    },
+    "node_modules/class-validator-jsonschema/node_modules/tslib": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
+      "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
+    },
     "node_modules/clean-stack": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -2194,14 +2247,6 @@
       "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
       "dev": true
     },
-    "node_modules/deepmerge": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
-      "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/defer-to-connect": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz",
@@ -3187,17 +3232,6 @@
       "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==",
       "dev": true
     },
-    "node_modules/fluent-json-schema": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/fluent-json-schema/-/fluent-json-schema-2.0.3.tgz",
-      "integrity": "sha512-Cd0Htv9mJfPVhrdBWNrKoIR/sYc4E2rlS+i3cooYwJi08uEree7daWNw0ZFw1djG4uajDxSjsiHPxAEgzgOqQQ==",
-      "dependencies": {
-        "deepmerge": "^4.2.2"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/from2": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
@@ -3499,6 +3533,14 @@
         "node": ">= 4"
       }
     },
+    "node_modules/google-libphonenumber": {
+      "version": "3.2.16",
+      "resolved": "https://registry.npmjs.org/google-libphonenumber/-/google-libphonenumber-3.2.16.tgz",
+      "integrity": "sha512-9Gzn78fJvCuNPYnbmUFFLhL0A4qBbSBs11+3cLKNuZX3lWKJ+1pSVS0C2bq0Yjq00cW2e8LZkHAxl+MQRGxGWA==",
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
     "node_modules/got": {
       "version": "11.8.1",
       "resolved": "https://registry.npmjs.org/got/-/got-11.8.1.tgz",
@@ -10915,6 +10957,14 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/openapi3-ts": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-2.0.1.tgz",
+      "integrity": "sha512-v6X3iwddhi276siej96jHGIqTx3wzVfMTmpGJEQDt7GPI7pI6sywItURLzpEci21SBRpPN/aOWSF5mVfFVNmcg==",
+      "dependencies": {
+        "yaml": "^1.10.0"
+      }
+    },
     "node_modules/optionator": {
       "version": "0.9.1",
       "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -13013,6 +13063,14 @@
         "spdx-expression-parse": "^3.0.0"
       }
     },
+    "node_modules/validator": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/validator/-/validator-13.0.0.tgz",
+      "integrity": "sha512-anYx5fURbgF04lQV18nEQWZ/3wHGnxiKdG4aL8J+jEDsm98n/sU/bey+tYk6tnGJzm7ioh5FoqrAiQ6m03IgaA==",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
     "node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -13179,7 +13237,6 @@
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz",
       "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==",
-      "dev": true,
       "engines": {
         "node": ">= 6"
       }
@@ -13995,6 +14052,11 @@
       "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
       "dev": true
     },
+    "@types/validator": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.0.0.tgz",
+      "integrity": "sha512-WAy5txG7aFX8Vw3sloEKp5p/t/Xt8jD3GRD9DacnFv6Vo8ubudAsRTXgxpQwU0mpzY/H8U4db3roDuCMjShBmw=="
+    },
     "@typescript-eslint/eslint-plugin": {
       "version": "4.13.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.13.0.tgz",
@@ -14621,6 +14683,46 @@
       "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
       "dev": true
     },
+    "class-transformer": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.1.tgz",
+      "integrity": "sha512-cKFwohpJbuMovS8xVLmn8N2AUbAuc8pVo4zEfsUVo8qgECOogns1WVk/FkOZoxhOPTyTYFckuoH+13FO+MQ8GA=="
+    },
+    "class-transformer-validator": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/class-transformer-validator/-/class-transformer-validator-0.9.1.tgz",
+      "integrity": "sha512-83/KFCyd6UiiwH6PlQS5y17O5TTx58CawvNI+XdrMs0Ig9QI5kiuzRqGcC/WrEpd1F7i4KIxCwdn6m4B6fl0jw==",
+      "requires": {}
+    },
+    "class-validator": {
+      "version": "0.12.2",
+      "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.12.2.tgz",
+      "integrity": "sha512-TDzPzp8BmpsbPhQpccB3jMUE/3pK0TyqamrK0kcx+ZeFytMA+O6q87JZZGObHHnoo9GM8vl/JppIyKWeEA/EVw==",
+      "requires": {
+        "@types/validator": "13.0.0",
+        "google-libphonenumber": "^3.2.8",
+        "tslib": ">=1.9.0",
+        "validator": "13.0.0"
+      }
+    },
+    "class-validator-jsonschema": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/class-validator-jsonschema/-/class-validator-jsonschema-2.1.1.tgz",
+      "integrity": "sha512-h9ZjaFgrtk7shrSbYGii08ow+mcrKVjzdBWZ/iHfrro6APOiTxYLTIASBneOfy+8uShocCsvBB2VtBFj8P/+Lg==",
+      "requires": {
+        "lodash": "^4.17.20",
+        "openapi3-ts": "^2.0.0",
+        "reflect-metadata": "^0.1.13",
+        "tslib": "^2.0.3"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
+          "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
+        }
+      }
+    },
     "clean-stack": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -14963,11 +15065,6 @@
       "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
       "dev": true
     },
-    "deepmerge": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
-      "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
-    },
     "defer-to-connect": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz",
@@ -15775,14 +15872,6 @@
       "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==",
       "dev": true
     },
-    "fluent-json-schema": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/fluent-json-schema/-/fluent-json-schema-2.0.3.tgz",
-      "integrity": "sha512-Cd0Htv9mJfPVhrdBWNrKoIR/sYc4E2rlS+i3cooYwJi08uEree7daWNw0ZFw1djG4uajDxSjsiHPxAEgzgOqQQ==",
-      "requires": {
-        "deepmerge": "^4.2.2"
-      }
-    },
     "from2": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
@@ -16033,6 +16122,11 @@
         }
       }
     },
+    "google-libphonenumber": {
+      "version": "3.2.16",
+      "resolved": "https://registry.npmjs.org/google-libphonenumber/-/google-libphonenumber-3.2.16.tgz",
+      "integrity": "sha512-9Gzn78fJvCuNPYnbmUFFLhL0A4qBbSBs11+3cLKNuZX3lWKJ+1pSVS0C2bq0Yjq00cW2e8LZkHAxl+MQRGxGWA=="
+    },
     "got": {
       "version": "11.8.1",
       "resolved": "https://registry.npmjs.org/got/-/got-11.8.1.tgz",
@@ -21738,6 +21832,14 @@
         "mimic-fn": "^2.1.0"
       }
     },
+    "openapi3-ts": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-2.0.1.tgz",
+      "integrity": "sha512-v6X3iwddhi276siej96jHGIqTx3wzVfMTmpGJEQDt7GPI7pI6sywItURLzpEci21SBRpPN/aOWSF5mVfFVNmcg==",
+      "requires": {
+        "yaml": "^1.10.0"
+      }
+    },
     "optionator": {
       "version": "0.9.1",
       "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -23395,6 +23497,11 @@
         "spdx-expression-parse": "^3.0.0"
       }
     },
+    "validator": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/validator/-/validator-13.0.0.tgz",
+      "integrity": "sha512-anYx5fURbgF04lQV18nEQWZ/3wHGnxiKdG4aL8J+jEDsm98n/sU/bey+tYk6tnGJzm7ioh5FoqrAiQ6m03IgaA=="
+    },
     "which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -23526,8 +23633,7 @@
     "yaml": {
       "version": "1.10.0",
       "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz",
-      "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==",
-      "dev": true
+      "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg=="
     },
     "yargs": {
       "version": "15.4.1",
diff --git a/package.json b/package.json
index 29ffc7e..3a72e4e 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
-  "name": "ts-autonetworks",
+  "name": "@k-net/ts-autonetwork",
   "version": "0.0.1",
-  "description": "TS-AutoNetwork is a network automation and proactive montiroing system",
+  "description": "TS-AutoNetwork is a YAML IPAM system",
   "main": "src/index.ts",
   "type": "module",
   "private": true,
@@ -44,8 +44,11 @@
     "@k-foss/ts-esnode": "^1.7.0",
     "ajv": "^7.0.3",
     "bullmq": "^1.14.0",
+    "class-transformer": "^0.3.1",
+    "class-transformer-validator": "^0.9.1",
+    "class-validator": "^0.12.2",
+    "class-validator-jsonschema": "^2.1.1",
     "fast-xml-parser": "^3.17.6",
-    "fluent-json-schema": "^2.0.3",
     "got": "^11.8.1",
     "ip-address": "^7.1.0",
     "js-yaml": "^3.14.1",
diff --git a/schemas/IPAM-Old.json b/schemas/IPAM-Old.json
new file mode 100644
index 0000000..f0d2b22
--- /dev/null
+++ b/schemas/IPAM-Old.json
@@ -0,0 +1 @@
+{"$schema":"http://json-schema.org/draft-07/schema#","definitions":{"community":{"type":"object","additionalProperties":false,"$id":"#community","description":"Community","properties":{"contact":{"type":"string","description":"Community Contact ID"},"name":{"type":"string","description":"Community Friendly Name"},"id":{"type":"string","description":"Short form community code","examples":["sxl"]},"sites":{"type":"array","items":{"$ref":"#/definitions/communitySite"}}},"required":["name","id","sites"]},"communitySite":{"type":"object","additionalProperties":false,"description":"Community Site","properties":{"id":{"type":"string","description":"Site short id"},"name":{"type":"string"},"type":{"type":"string","enum":["Network Headend","Community Center","Health Center","Cell Tower","Colocation","Band Office","School","Lake HeadU","KO Office","Tower"]},"devices":{"type":"array","items":{"$ref":"#/definitions/device"}}},"required":["id","name"]},"contact":{"type":"object","additionalProperties":false,"$id":"#contact","description":"Community Contact","properties":{"id":{"$ref":"#/definitions/contactId"},"name":{"type":"string","description":"Contact Full Name"}},"required":["id","name"]},"contactId":{"type":"string","description":"Unique Identifier for referencing Contact"},"device":{"type":"object","additionalProperties":false,"$id":"#device","description":"Network Device","properties":{"id":{"type":"string","description":"Chained ID"},"name":{"type":"string","description":"Friendly name"},"type":{"$ref":"#/definitions/networkDeviceType"}},"required":["id","name"]},"networkcircuit":{"type":"object","additionalProperties":false,"description":"NetworkCircuit","properties":{"id":{"type":"string","description":"Circuit Id"},"speed":{"type":"string","description":"Circuit Speed"}},"required":["id"]},"networkDeviceLink":{"type":"object","additionalProperties":false,"description":"Link a Network to a device","properties":{"id":{"type":"string","description":"Device id"},"interface":{"type":"string","description":"Device interface"}},"required":["id"]},"circuitLocation":{"type":"object","description":"Traditional external circuits","additionalProperties":false,"properties":{"id":{"type":"string","description":"External circuit id"},"provider":{"type":"string","description":"External circuit provider"},"communuity":{"type":"string","description":"Community ID"},"address":{"type":"string","description":"Address provided to external provider"},"demarcSpeed":{"type":"string","enum":["10M","100M","200M","300M","500M","1G","5G","10G"]}}},"circuit":{"type":"object","description":"Community Circuit","additionalProperties":false,"properties":{"id":{"type":"string","description":"Circuit ID"},"sideA":{"$ref":"#/definitions/circuitSide"},"sideZ":{"$ref":"#/definitions/circuitSide"},"speed":{"type":"string"}},"required":["id","sideA","sideZ"]},"circuitSide":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","description":"Circuit Location Id"}},"required":["id"]},"network":{"type":"object","additionalProperties":false,"description":"Network","properties":{"prefix":{"type":"string","description":"Network Prefix"},"description":{"type":"string"},"circuit":{"$ref":"#/definitions/networkcircuit"},"nsServers":{"type":"array","items":{"type":"string","description":"Reverse DNS NS Server","format":"hostname"}},"type":{"type":"string","description":"Network Type","enum":["UNALLOCATED","EXTERNAL"]},"contactId":{"$ref":"#/definitions/contactId"},"hosts":{"type":"array","items":{"$ref":"#/definitions/networkHost"}},"ranges":{"type":"array","items":{"$ref":"#/definitions/networkRange"}},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Children Networks"}}},"networkHost":{"type":"object","additionalProperties":false,"description":"Indivual Network host","properties":{"ip":{"type":"string","description":"Host IP Address","format":"ipv4"},"hostname":{"type":"string","description":"Hostname for reverse DNS creation","format":"hostname"},"contactId":{"$ref":"#/definitions/contactId"},"description":{"type":"string"},"device":{"$ref":"#/definitions/networkDeviceLink"}},"required":["ip"]},"networkRange":{"type":"object","additionalProperties":false,"description":"Network Range","properties":{"start":{"type":"string","description":"Start IP for the range","format":"ipv4"},"end":{"type":"string","description":"End IP for the range","format":"ipv4"},"description":{"type":"string"},"type":{"type":"string","enum":["DHCP","RESERVED","STATIC","FREE","unallocated"]}},"required":["start","end"]},"networkDeviceType":{"type":"string","enum":["router","switch","access-point","server","modem","firewall","UPS","cell-vpn","cell-gw"]},"networkDeviceInterfaceType":{"type":"string","enum":["FastEthernet","GigabitEthernet","TenGigabitEthernet"]}},"type":"object","additionalProperties":false,"description":"IPAM Configuration File","properties":{"communities":{"type":"array","items":{"$ref":"#/definitions/community"}},"circuits":{"type":"array","items":{"$ref":"#/definitions/circuit"},"uniqueItems":true,"description":"Circuits"},"circuitLocations":{"type":"array","items":{"$ref":"#/definitions/circuitLocation"},"uniqueItems":true,"description":"External Circuits"},"contacts":{"type":"array","items":{"$ref":"#/definitions/contact"},"uniqueItems":true,"description":"Contact Information"},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Networks"}},"required":["communities","circuits","circuitLocations","contacts","networks"]}
\ No newline at end of file
diff --git a/schemas/IPAM.json b/schemas/IPAM.json
index f0d2b22..09c65d5 100644
--- a/schemas/IPAM.json
+++ b/schemas/IPAM.json
@@ -1 +1 @@
-{"$schema":"http://json-schema.org/draft-07/schema#","definitions":{"community":{"type":"object","additionalProperties":false,"$id":"#community","description":"Community","properties":{"contact":{"type":"string","description":"Community Contact ID"},"name":{"type":"string","description":"Community Friendly Name"},"id":{"type":"string","description":"Short form community code","examples":["sxl"]},"sites":{"type":"array","items":{"$ref":"#/definitions/communitySite"}}},"required":["name","id","sites"]},"communitySite":{"type":"object","additionalProperties":false,"description":"Community Site","properties":{"id":{"type":"string","description":"Site short id"},"name":{"type":"string"},"type":{"type":"string","enum":["Network Headend","Community Center","Health Center","Cell Tower","Colocation","Band Office","School","Lake HeadU","KO Office","Tower"]},"devices":{"type":"array","items":{"$ref":"#/definitions/device"}}},"required":["id","name"]},"contact":{"type":"object","additionalProperties":false,"$id":"#contact","description":"Community Contact","properties":{"id":{"$ref":"#/definitions/contactId"},"name":{"type":"string","description":"Contact Full Name"}},"required":["id","name"]},"contactId":{"type":"string","description":"Unique Identifier for referencing Contact"},"device":{"type":"object","additionalProperties":false,"$id":"#device","description":"Network Device","properties":{"id":{"type":"string","description":"Chained ID"},"name":{"type":"string","description":"Friendly name"},"type":{"$ref":"#/definitions/networkDeviceType"}},"required":["id","name"]},"networkcircuit":{"type":"object","additionalProperties":false,"description":"NetworkCircuit","properties":{"id":{"type":"string","description":"Circuit Id"},"speed":{"type":"string","description":"Circuit Speed"}},"required":["id"]},"networkDeviceLink":{"type":"object","additionalProperties":false,"description":"Link a Network to a device","properties":{"id":{"type":"string","description":"Device id"},"interface":{"type":"string","description":"Device interface"}},"required":["id"]},"circuitLocation":{"type":"object","description":"Traditional external circuits","additionalProperties":false,"properties":{"id":{"type":"string","description":"External circuit id"},"provider":{"type":"string","description":"External circuit provider"},"communuity":{"type":"string","description":"Community ID"},"address":{"type":"string","description":"Address provided to external provider"},"demarcSpeed":{"type":"string","enum":["10M","100M","200M","300M","500M","1G","5G","10G"]}}},"circuit":{"type":"object","description":"Community Circuit","additionalProperties":false,"properties":{"id":{"type":"string","description":"Circuit ID"},"sideA":{"$ref":"#/definitions/circuitSide"},"sideZ":{"$ref":"#/definitions/circuitSide"},"speed":{"type":"string"}},"required":["id","sideA","sideZ"]},"circuitSide":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","description":"Circuit Location Id"}},"required":["id"]},"network":{"type":"object","additionalProperties":false,"description":"Network","properties":{"prefix":{"type":"string","description":"Network Prefix"},"description":{"type":"string"},"circuit":{"$ref":"#/definitions/networkcircuit"},"nsServers":{"type":"array","items":{"type":"string","description":"Reverse DNS NS Server","format":"hostname"}},"type":{"type":"string","description":"Network Type","enum":["UNALLOCATED","EXTERNAL"]},"contactId":{"$ref":"#/definitions/contactId"},"hosts":{"type":"array","items":{"$ref":"#/definitions/networkHost"}},"ranges":{"type":"array","items":{"$ref":"#/definitions/networkRange"}},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Children Networks"}}},"networkHost":{"type":"object","additionalProperties":false,"description":"Indivual Network host","properties":{"ip":{"type":"string","description":"Host IP Address","format":"ipv4"},"hostname":{"type":"string","description":"Hostname for reverse DNS creation","format":"hostname"},"contactId":{"$ref":"#/definitions/contactId"},"description":{"type":"string"},"device":{"$ref":"#/definitions/networkDeviceLink"}},"required":["ip"]},"networkRange":{"type":"object","additionalProperties":false,"description":"Network Range","properties":{"start":{"type":"string","description":"Start IP for the range","format":"ipv4"},"end":{"type":"string","description":"End IP for the range","format":"ipv4"},"description":{"type":"string"},"type":{"type":"string","enum":["DHCP","RESERVED","STATIC","FREE","unallocated"]}},"required":["start","end"]},"networkDeviceType":{"type":"string","enum":["router","switch","access-point","server","modem","firewall","UPS","cell-vpn","cell-gw"]},"networkDeviceInterfaceType":{"type":"string","enum":["FastEthernet","GigabitEthernet","TenGigabitEthernet"]}},"type":"object","additionalProperties":false,"description":"IPAM Configuration File","properties":{"communities":{"type":"array","items":{"$ref":"#/definitions/community"}},"circuits":{"type":"array","items":{"$ref":"#/definitions/circuit"},"uniqueItems":true,"description":"Circuits"},"circuitLocations":{"type":"array","items":{"$ref":"#/definitions/circuitLocation"},"uniqueItems":true,"description":"External Circuits"},"contacts":{"type":"array","items":{"$ref":"#/definitions/contact"},"uniqueItems":true,"description":"Contact Information"},"networks":{"type":"array","items":{"$ref":"#/definitions/network"},"uniqueItems":true,"description":"Networks"}},"required":["communities","circuits","circuitLocations","contacts","networks"]}
\ No newline at end of file
+{"$schema":"http://json-schema.org/draft-07/schema#","definitions":{"CircuitSide":{"properties":{"id":{"type":"string","description":"Circuit ID referencing the CircuitLocation ID"}},"type":"object","required":["id"],"title":"Circuit Side","description":"A single circuit connection","additionalProperties":false},"Circuit":{"properties":{"id":{"type":"string","description":"Unique Circuit ID used for refences from other objects"},"sideAID":{"$ref":"#/definitions/CircuitSide","type":"string"},"sideZID":{"$ref":"#/definitions/CircuitSide","type":"string"},"speed":{"type":"string","description":"EVC Speed that the circuit is capable of achiving"}},"type":"object","required":["id","sideAID","sideZID","speed"],"title":"Circuit","description":"Circuit connecting two sites, or what is normally an \"EVC\"","additionalProperties":false},"CircuitLocation":{"properties":{"id":{"type":"string","description":"Unique Circuit Location ID used for refences from other objects"},"address":{"type":"string","description":"Location of the circuit demarc/termination provided to the Circuit Provider"},"provider":{"type":"string","description":"Name of the circuit provider"},"communuityId":{"type":"string","description":"Reference ID of the Community the circuit is within"},"demarcSpeed":{"type":"string","description":"Demarc Port speed","enum":["10M","100M","200M","300M","500M","1G","5G","10G"]}},"type":"object","required":["id","address","provider","communuityId","demarcSpeed"],"title":"Circuit Location","description":"Circuit location, or what circuit providers think of as \"circuits\"","additionalProperties":false},"Contact":{"properties":{"id":{"type":"string"},"name":{"type":"string","description":"Friendly contact name"}},"type":"object","required":["id","name"],"title":"Contact","description":"Contact for community/site/prefix","additionalProperties":false},"NetworkHostDevice":{"properties":{"id":{"type":"string","description":"Reference ID for Site Device"},"interface":{"type":"string","description":"Interface on the Site Device with the Host IP address configured"}},"type":"object","required":["id"],"title":"NetworkHostDevice","description":"Community Site Device connection for a Network Host"},"NetworkHost":{"properties":{"ip":{"type":"string","description":"IP Address for this host entry"},"description":{"type":"string","description":"Friendly Description for the Network Host"},"device":{"deprecated":true},"deviceId":{"type":"string","description":"Site Device Reference ID"},"deviceInterface":{"description":"Site Device Interface"},"hostname":{"type":"string","description":"Friendly Description for the Network Host"},"contactId":{"type":"string","description":"Reference ID for Contact"}},"type":"object","required":["ip"],"title":"NetworkHost","description":"TODO","additionalProperties":false},"NetworkRange":{"properties":{"start":{"format":"ipv4","type":"string","description":"Start IP of the range"},"end":{"format":"ipv4","type":"string","description":"Start IP of the range"},"description":{"type":"string","description":"Friendly description of the range"},"type":{"type":"string","description":"Usage/type of this range","enum":["DHCP","RESERVED","STATIC","FREE","unallocated"]}},"type":"object","required":["start","end","type"],"title":"NetworkRange"},"Network":{"properties":{"prefix":{"type":"string","description":"Network Prefix"},"description":{"type":"string","description":"Description for this network"},"type":{"type":"string","description":"Usage/type for this network","enum":["UNALLOCATED","EXTERNAL"]},"circuitId":{"type":"string","description":"Reference Circuit ID"},"networks":{"items":{"$ref":"#/definitions/Network"},"type":"array"},"ranges":{"items":{"$ref":"#/definitions/NetworkRange"},"type":"array"},"parentNetworkId":{"type":"string"},"hosts":{"items":{"$ref":"#/definitions/NetworkHost"},"type":"array"},"contactId":{"type":"string","description":"Reference Contact ID"},"nsServers":{"items":{"type":"string"},"type":"array","description":"Authorative name server to forward reverse DNS requests to"}},"type":"object","required":["prefix"],"title":"Network","description":"Network object","additionalProperties":false},"SiteDevice":{"properties":{"id":{"type":"string","description":"Unique Network Device ID used for refences from other objects"},"name":{"type":"string","description":"Friendly name for this device"},"type":{"type":"string","enum":["router","switch","access-point","server","modem","firewall","UPS","cell-vpn","cell-gw"],"description":"Type of the device, used for tracing, and for reverse dns creation"}},"type":"object","required":["id","name"],"title":"SiteDevice"},"Site":{"properties":{"id":{"type":"string","description":"Unique Site ID used for refences from other objects, generally best practice to do COMMUNITYID.SITE_TYPE"},"name":{"type":"string","description":"Friendly name of the community site"},"type":{"type":"string","description":"Type of the site","enum":["Network Headend","Community Center","Health Center","Cell Tower","Colocation","Band Office","School","Lake HeadU","KO Office","Tower"]},"devices":{"items":{"$ref":"#/definitions/SiteDevice"},"type":"array"}},"type":"object","required":["id","name","devices"],"title":"Site","description":"Site within a community which contains devices","additionalProperties":false},"Community":{"properties":{"name":{"type":"string","description":"Friendly name for the community"},"id":{"type":"string","description":"Unique community ID used for refences from other objects"},"contactId":{"type":"string","description":"Unique contact ID reference"},"sites":{"items":{"$ref":"#/definitions/Site"},"type":"array"}},"type":"object","required":["name","id","contactId","sites"],"title":"Community Object","description":"Community in which service is provided.","additionalProperties":false}},"$id":"IPAM","properties":{"contacts":{"items":{"$ref":"#/definitions/Contact"},"type":"array"},"communities":{"items":{"$ref":"#/definitions/Community"},"type":"array"},"circuitLocations":{"items":{"$ref":"#/definitions/CircuitLocation"},"type":"array"},"circuits":{"items":{"$ref":"#/definitions/Circuit"},"type":"array"},"networks":{"items":{"$ref":"#/definitions/Network"},"type":"array"}},"type":"object","required":["contacts","communities","circuitLocations","circuits","networks"],"title":"IPAM File","description":"IPAM","additionalProperties":false}
\ No newline at end of file
diff --git a/schemas/problem-matcher.json b/schemas/problem-matcher.json
new file mode 100644
index 0000000..f38323e
--- /dev/null
+++ b/schemas/problem-matcher.json
@@ -0,0 +1,18 @@
+{
+  "problemMatcher": [
+    {
+      "owner": "eslint-compact",
+      "pattern": [
+        {
+          "regexp": "^(.+):\\sline\\s(\\d+),\\s(Error|Warning|Info)\\s-\\s(.+)\\s\\((.+)\\)$",
+          "file": 1,
+          "line": 2,
+          "column": 2,
+          "severity": 3,
+          "message": 4,
+          "code": 5
+        }
+      ]
+    }
+  ]
+}
diff --git a/src/Library/Context.ts b/src/Library/Context.ts
new file mode 100644
index 0000000..462e05a
--- /dev/null
+++ b/src/Library/Context.ts
@@ -0,0 +1,37 @@
+// src/Library/Context.ts
+import { ContainerInstance, Token, Container } from 'typedi';
+import { logger, LogMode } from './Logger';
+
+export interface Context {
+  container: ContainerInstance;
+}
+
+export const contextToken = new Token('contextToken');
+
+/**
+ * Create Context Object.
+ * @param context Context Object
+ *
+ * @returns Promise resolving to the Container object
+ */
+export function createContext(
+  context: Context = {
+    container: Container.of(),
+  },
+): Context {
+  logger.log(LogMode.DEBUG, `createContext()`, context.container);
+
+  context.container.set({
+    id: contextToken,
+    value: context,
+    global: true,
+  });
+
+  Container.set({
+    id: contextToken,
+    value: context,
+    global: true,
+  });
+
+  return context;
+}
diff --git a/src/Modules/Circuits/Circuit.ts b/src/Modules/Circuits/Circuit.ts
index 7cf3ba8..72c6c63 100644
--- a/src/Modules/Circuits/Circuit.ts
+++ b/src/Modules/Circuits/Circuit.ts
@@ -1,22 +1,38 @@
 // src/Modules/Circuits/Circuit.ts
-import Container, { Service } from 'typedi';
-import { createContainerName } from '../../Utils/Containers';
-import {
-  Circuit as IPAMCircuit,
-  CircuitSide as IPAMCircuitSide,
-} from '../IPAM/IPAMConfig.gen';
+import { IsString } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Service, Container } from 'typedi';
 import xbytes from 'xbytes';
+import { createContainerName } from '../../Utils/Containers';
+import { IsValidID } from '../../Utils/Validator';
 import { Network } from '../Networks/Network';
 import { CircuitLocation } from './CircuitLocation';
 
+@JSONSchema({
+  title: 'Circuit',
+  description: 'Circuit connecting two sites, or what is normally an "EVC"',
+  additionalProperties: false,
+})
 @Service()
-export class Circuit implements IPAMCircuit {
+export class Circuit {
+  @IsString()
+  @JSONSchema({
+    description: 'Unique Circuit ID used for refences from other objects',
+  })
   public id: string;
 
-  public sideA: IPAMCircuitSide;
+  @IsString()
+  @IsValidID('CIRCUITLOCATION')
+  public sideAID: string;
 
-  public sideZ: IPAMCircuitSide;
+  @IsString()
+  @IsValidID('CIRCUITLOCATION')
+  public sideZID: string;
 
+  @IsString()
+  @JSONSchema({
+    description: 'EVC Speed that the circuit is capable of achiving',
+  })
   public speed: string;
 
   public get networks(): Network[] {
@@ -43,18 +59,10 @@ export class Circuit implements IPAMCircuit {
   }
 
   public get sideACircuitLocation(): CircuitLocation {
-    return Container.get(
-      createContainerName('CIRCUIT_LOCATION', this.sideA.id),
-    );
+    return Container.get(createContainerName('CIRCUITLOCATION', this.sideAID));
   }
 
   public get sideZCircuitLocation(): Circuit {
-    return Container.get(
-      createContainerName('CIRCUIT_LOCATION', this.sideZ.id),
-    );
-  }
-
-  public constructor(options: Partial) {
-    Object.assign(this, options);
+    return Container.get(createContainerName('CIRCUITLOCATION', this.sideZID));
   }
 }
diff --git a/src/Modules/Circuits/CircuitController.ts b/src/Modules/Circuits/CircuitController.ts
new file mode 100644
index 0000000..502ed08
--- /dev/null
+++ b/src/Modules/Circuits/CircuitController.ts
@@ -0,0 +1,54 @@
+// src/Modules/Circuits/CircuitController.ts
+import { Inject, Service, Container } from 'typedi';
+import { createContainerName } from '../../Utils/Containers';
+import { IPAM } from '../IPAM/IPAM';
+import { SiteDevice } from '../SiteDevice/SiteDevice';
+import { Site } from '../Sites/Site';
+
+@Service()
+export class CircuitController {
+  @Inject('ipam')
+  public ipam: IPAM;
+
+  public get communityCount(): number {
+    return this.ipam.communities.length;
+  }
+
+  public rootDevice: SiteDevice;
+
+  public rootSite: Site;
+
+  public constructor(
+    @Inject('totalCommunities')
+    public totalCommunities: number,
+    @Inject('rootSiteId') public rootSiteId: string,
+    @Inject('rootDeviceId')
+    public rootDeviceId: string,
+  ) {
+    this.rootSite = Container.get(createContainerName('SITE', this.rootSiteId));
+
+    this.rootDevice = Container.get(
+      createContainerName('SITEDEVICE', this.rootDeviceId),
+    );
+  }
+
+  public listCircuits(): void {
+    for (const networkHost of this.rootDevice.getNetworkHosts()) {
+      const circuit = networkHost.parentNetwork.circuit;
+
+      if (networkHost.device?.interface && circuit?.id) {
+        console.log(
+          `${
+            networkHost.device.interface
+          } circuit run at ${circuit
+            .parsedCircuitSpeed()
+            .convertTo('Mb')} for community: ${
+            circuit.sideACircuitLocation.communuity.name
+          }`,
+        );
+      } else {
+        console.log(`No device Interface or circuit`, networkHost);
+      }
+    }
+  }
+}
diff --git a/src/Modules/Circuits/CircuitLocation.ts b/src/Modules/Circuits/CircuitLocation.ts
index 421e1d6..bc2a531 100644
--- a/src/Modules/Circuits/CircuitLocation.ts
+++ b/src/Modules/Circuits/CircuitLocation.ts
@@ -1,25 +1,55 @@
 // src/Modules/Circuits/CircuitLocation.ts
-import Container, { Service } from 'typedi';
+import { IsString } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Service, Container } from 'typedi';
 import { createContainerName } from '../../Utils/Containers';
+import { IsValidID } from '../../Utils/Validator';
 import { Community } from '../Communities/Community';
-import { CircuitLocation as IPAMCircuitLocation } from '../IPAM/IPAMConfig.gen';
+import { CommunityCircuitSpeed } from '../CommunityCircuits/CommunityCircuitSpeed';
 
+@JSONSchema({
+  title: 'Circuit Location',
+  description:
+    'Circuit location, or what circuit providers think of as "circuits"',
+  additionalProperties: false,
+})
 @Service()
-export class CircuitLocation
-  implements Omit {
+export class CircuitLocation {
+  @IsString()
+  @JSONSchema({
+    description:
+      'Unique Circuit Location ID used for refences from other objects',
+  })
   public id: string;
 
+  @IsString()
+  @JSONSchema({
+    description:
+      'Location of the circuit demarc/termination provided to the Circuit Provider',
+  })
   public address: string;
 
+  @IsString()
+  @JSONSchema({
+    description: 'Name of the circuit provider',
+  })
   public provider: string;
 
+  @IsString()
+  @IsValidID('COMMUNITY')
+  @JSONSchema({
+    description: 'Reference ID of the Community the circuit is within',
+  })
   public communuityId: string;
 
+  @IsString()
+  @JSONSchema({
+    description: 'Demarc Port speed',
+    enum: Object.values(CommunityCircuitSpeed),
+  })
+  public demarcSpeed: CommunityCircuitSpeed;
+
   public get communuity(): Community {
     return Container.get(createContainerName('COMMUNITY', this.communuityId));
   }
-
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
 }
diff --git a/src/Modules/Circuits/CircuitSchema.ts b/src/Modules/Circuits/CircuitSchema.ts
deleted file mode 100644
index 8286cbe..0000000
--- a/src/Modules/Circuits/CircuitSchema.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// src/Modules/CommunityCircuits/CommunityCircuitConfigSchema.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const circuitSchema = jsonSchema
-  .object()
-  .description('Community Circuit')
-  .additionalProperties(false)
-  .prop('id', jsonSchema.string().description('Circuit ID').required())
-  .prop('sideA', jsonSchema.ref('#/definitions/circuitSide').required())
-  .prop('sideZ', jsonSchema.ref('#/definitions/circuitSide').required())
-  .prop('speed', jsonSchema.string());
diff --git a/src/Modules/Circuits/CircuitSide.ts b/src/Modules/Circuits/CircuitSide.ts
new file mode 100644
index 0000000..d27a452
--- /dev/null
+++ b/src/Modules/Circuits/CircuitSide.ts
@@ -0,0 +1,20 @@
+// src/Modules/Circuits/CircuitSide.ts
+import { IsString } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Service } from 'typedi';
+import { IsValidID } from '../../Utils/Validator';
+
+@JSONSchema({
+  title: 'Circuit Side',
+  description: 'A single circuit connection',
+  additionalProperties: false,
+})
+@Service()
+export class CircuitSide {
+  @IsString()
+  @IsValidID('CIRCUITLOCATION')
+  @JSONSchema({
+    description: 'Circuit ID referencing the CircuitLocation ID',
+  })
+  public id: string;
+}
diff --git a/src/Modules/Circuits/CircuitSideSchema.ts b/src/Modules/Circuits/CircuitSideSchema.ts
deleted file mode 100644
index 3ae4225..0000000
--- a/src/Modules/Circuits/CircuitSideSchema.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// src/Modules/Circuits/CircuitSideSchema.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const circuitSideSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .prop(
-    'id',
-    jsonSchema.string().description('Circuit Location Id').required(),
-  );
diff --git a/src/Modules/Communities/Community.ts b/src/Modules/Communities/Community.ts
index 39d0eb6..40f7653 100644
--- a/src/Modules/Communities/Community.ts
+++ b/src/Modules/Communities/Community.ts
@@ -1,29 +1,51 @@
 // src/Modules/Communities/Community.ts
-import Container, { Service, Token } from 'typedi';
-import { createContainerName } from '../../Utils/Containers';
+import { Service, Token, Container } from 'typedi';
+import { createContainerName, setContainer } from '../../Utils/Containers';
 import { Site } from '../Sites/Site';
 import { Contact } from '../Contacts/Contact';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { IsString, ValidateNested } from 'class-validator';
+import { Transform, Type } from 'class-transformer';
+import { IsValidID } from '../../Utils/Validator';
 
 export const CommunitiesToken = new Token('communities');
 
+@JSONSchema({
+  title: 'Community Object',
+  description: 'Community in which service is provided.',
+  additionalProperties: false,
+})
 @Service()
 export class Community {
+  @IsString()
+  @JSONSchema({
+    description: 'Friendly name for the community',
+  })
   public name: string;
 
+  @IsString()
+  @JSONSchema({
+    description: 'Unique community ID used for refences from other objects',
+  })
   public id: string;
 
-  /**
-   * Unique Contact Id Reference
-   */
+  @IsString()
+  @IsValidID('CONTACT')
+  @JSONSchema({
+    description: 'Unique contact ID reference',
+  })
   public contactId: string;
 
+  @ValidateNested({ each: true })
+  @Transform((items: Site[]) => {
+    items.map((item) => setContainer('SITE', item.id, item));
+
+    return items;
+  }, {})
+  @Type(() => Site)
   public sites: Site[];
 
   public get contact(): Contact {
     return Container.get(createContainerName('CONTACT', this.contactId));
   }
-
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
 }
diff --git a/src/Modules/Communities/CommunitySchema.ts b/src/Modules/Communities/CommunitySchema.ts
deleted file mode 100644
index 37a0184..0000000
--- a/src/Modules/Communities/CommunitySchema.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// src/Modules/Communities/CommunitySchema.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const communitySchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .id('#community')
-  .description('Community')
-  .prop('contact', jsonSchema.string().description('Community Contact ID'))
-  .prop(
-    'name',
-    jsonSchema.string().description('Community Friendly Name').required(),
-  )
-  .prop(
-    'id',
-    jsonSchema
-      .string()
-      .description('Short form community code')
-      .examples(['sxl'])
-      .required(),
-  )
-  .prop(
-    'sites',
-    jsonSchema
-      .array()
-      .items(jsonSchema.ref('#/definitions/communitySite'))
-      .required(),
-  );
diff --git a/src/Modules/CommunityCircuits/CircuitLocationSchema.ts b/src/Modules/CommunityCircuits/CircuitLocationSchema.ts
deleted file mode 100644
index d5a31d4..0000000
--- a/src/Modules/CommunityCircuits/CircuitLocationSchema.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// src/Modules/CommunityCircuits/CommunityCircuitLocationSchema.ts
-import jsonSchema from 'fluent-json-schema';
-import { CommunityCircuitSpeed } from './CommunityCircuitSpeed';
-
-export const circuitLocationSchema = jsonSchema
-  .object()
-  .description('Traditional external circuits')
-  .additionalProperties(false)
-  .prop('id', jsonSchema.string().description('External circuit id'))
-  .prop(
-    'provider',
-    jsonSchema.string().description('External circuit provider'),
-  )
-  .prop('communuity', jsonSchema.string().description('Community ID'))
-  .prop(
-    'address',
-    jsonSchema.string().description('Address provided to external provider'),
-  )
-  .prop(
-    'demarcSpeed',
-    jsonSchema.string().enum(Object.values(CommunityCircuitSpeed)),
-  );
diff --git a/src/Modules/Contacts/Contact.test.ts b/src/Modules/Contacts/Contact.test.ts
index a38f6eb..5cf2d09 100644
--- a/src/Modules/Contacts/Contact.test.ts
+++ b/src/Modules/Contacts/Contact.test.ts
@@ -3,97 +3,122 @@ import { TestSuite } from '@k-foss/ts-estests';
 import { deepStrictEqual } from 'assert';
 import { resolve } from 'path';
 import { fileURLToPath } from 'url';
-import { ipamConfigController } from '../IPAM/IPAMConfigController';
+import { IPAMController } from '../IPAM/IPAMController';
 
-export class ContactTestSuite extends TestSuite {
+export class ContactSuite extends TestSuite {
   public testName = 'Contact Test Suite';
 
   public async test(): Promise {
-    const ipam = await ipamConfigController.loadFile(
-      resolve(
-        fileURLToPath(import.meta.url),
-        '../fixtures/ContactSample1.yaml',
-      ),
+    const ipamController = IPAMController.createIPAM();
+
+    const contactFixture1Path = resolve(
+      fileURLToPath(import.meta.url),
+      '../fixtures/ContactSample1.yaml',
     );
 
-    const contact1 = ipam.contacts[0];
-    const contact2 = ipam.contacts[1];
-    const contact3 = ipam.contacts[2];
+    const config = await ipamController.loadIPAM(contactFixture1Path);
 
-    deepStrictEqual(
-      contact1.id,
-      'lab1.kfj',
-      'ipam.contacts[0].id === lab1.kfj',
+    /**
+     * Contacts
+     */
+
+    /**
+     * Contact 1 - Kristian Jones
+     */
+    const kristianjones1 = config.contacts.find(
+      (contact) => contact.name === 'Kristian Jones',
     );
 
     deepStrictEqual(
-      contact2.id,
-      'core1.hello',
-      'ipam.contacts[1].id === core1.hello',
+      kristianjones1?.id,
+      'lab1.kfj',
+      'kristianjones1.id === lab1.kfj',
     );
-
     deepStrictEqual(
-      contact3.id,
-      'net.test',
-      'ipam.contacts[2].id === net.test',
+      kristianjones1?.name,
+      'Kristian Jones',
+      'kristianjones1.name === Kristian Jones',
     );
 
-    const community1 = ipam.communities[0];
-    const community2 = ipam.communities[1];
+    /**
+     * Contact 2 - Hello World
+     */
+    const helloworld1 = config.contacts.find(
+      (contact) => contact.name === 'Hello World',
+    );
 
     deepStrictEqual(
-      community1.contactId,
-      'lab1.kfj',
-      'ipam.communities[0].contactId === lab1.kfj',
+      helloworld1?.id,
+      'core1.hello',
+      'helloworld1.id === core1.hello',
     );
     deepStrictEqual(
-      community1.contact.id,
-      'lab1.kfj',
-      'ipam.communities[0].contact.id === lab1.kfj',
+      helloworld1?.name,
+      'Hello World',
+      'helloworld1.name === Hello World',
+    );
+
+    /**
+     * Contact 3 - HelloTest
+     */
+    const hellotest1 = config.contacts.find(
+      (contact) => contact.name === 'HelloTest',
     );
 
+    deepStrictEqual(hellotest1?.id, 'net.test', 'hellotest1.id === net.test');
     deepStrictEqual(
-      community2.contactId,
-      'core1.hello',
-      'ipam.communities[1].contactId === core1.hello',
+      hellotest1?.name,
+      'HelloTest',
+      'hellotest1.name === HelloTest',
+    );
+
+    /**
+     * Contact 4 - Third Party Provider
+     */
+    const thirdPartyProvider1 = config.contacts.find(
+      (contact) => contact.id === 'thirdparty.core',
     );
+
     deepStrictEqual(
-      community2.contact.id,
-      'core1.hello',
-      'ipam.communities[1].contact.id === core1.hello',
+      thirdPartyProvider1?.id,
+      'thirdparty.core',
+      'thirdPartyProvider1?.id === thirdparty.core',
     );
     deepStrictEqual(
-      community2.contact,
-      contact2,
-      'ipam.communities[1].contact === ipam.contacts[1]',
+      thirdPartyProvider1?.name,
+      'Third Party Provider 1',
+      'thirdPartyProvider1?.name === Third Party Provider 1',
     );
 
-    const network1 = ipam.networks[0];
-
-    if (network1.networks) {
-      const subnetwork1 = network1.networks[0];
-
-      console.log(subnetwork1.prefix, subnetwork1.contact, subnetwork1.circuit);
-
-      deepStrictEqual(subnetwork1.contact?.id, network1.contactId);
-    }
+    /**
+     * Networks 1 - HelloTest
+     */
+    const coreNetwork = config.networks.find(
+      (network) => network.prefix === '1.1.1.0/24',
+    );
 
     deepStrictEqual(
-      network1.contactId,
-      'net.test',
-      'ipam.networks[0].contactId === net.test',
+      coreNetwork?.contactId,
+      hellotest1.id,
+      'coreNetwork?.contactId === hellotest1.id',
     );
-
     deepStrictEqual(
-      network1.contact?.id,
-      'net.test',
-      'ipam.networks[0].contact?.id === net.test',
+      coreNetwork?.contact,
+      hellotest1,
+      'coreNetwork?.contact === hellotest1',
+    );
+
+    /**
+     * Network 1 - Sub Network 1 - External Provider
+     */
+    const coreNetworkSub1 = coreNetwork.networks.find(
+      (network) => network.prefix === '1.1.1.0/30',
     );
 
     deepStrictEqual(
-      network1.contact,
-      contact3,
-      'ipam.networks[0].contact === ipam.contacts[2]',
+      coreNetworkSub1?.prefix,
+      '1.1.1.0/30',
+      'coreNetworkSub1?.prefix === 1.1.1.0/30',
     );
   }
 }
diff --git a/src/Modules/Contacts/Contact.ts b/src/Modules/Contacts/Contact.ts
index a9bfde7..0c7fa1c 100644
--- a/src/Modules/Contacts/Contact.ts
+++ b/src/Modules/Contacts/Contact.ts
@@ -1,14 +1,25 @@
 // src/Modules/CommunityContacts/CommunityContact.ts
+import { JSONSchema } from 'class-validator-jsonschema';
 import { Service } from 'typedi';
-import { Contact as IPAMContact } from '../IPAM/IPAMConfig.gen';
+import { IsString } from 'class-validator';
 
+@JSONSchema({
+  title: 'Contact',
+  description: 'Contact for community/site/prefix',
+  additionalProperties: false,
+})
 @Service()
-export class Contact implements IPAMContact {
+export class Contact {
+  @IsString()
   public id: string;
 
-  public name: string;
+  /**
+   * TODO: Determine contact fields and finish
+   */
 
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
+  @IsString()
+  @JSONSchema({
+    description: 'Friendly contact name',
+  })
+  public name: string;
 }
diff --git a/src/Modules/Contacts/ContactSchema.ts b/src/Modules/Contacts/ContactSchema.ts
deleted file mode 100644
index bb95453..0000000
--- a/src/Modules/Contacts/ContactSchema.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// src/Modules/CommunityContacts/CommunityContactConfigSchema.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const contactSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .id('#contact')
-  .description('Community Contact')
-  .prop('id', jsonSchema.ref('#/definitions/contactId').required())
-  .prop(
-    'name',
-    jsonSchema.string().description('Contact Full Name').required(),
-  );
diff --git a/src/Modules/Contacts/fixtures/ContactSample1.yaml b/src/Modules/Contacts/fixtures/ContactSample1.yaml
index cefe065..9e1e5ef 100644
--- a/src/Modules/Contacts/fixtures/ContactSample1.yaml
+++ b/src/Modules/Contacts/fixtures/ContactSample1.yaml
@@ -1,52 +1,65 @@
 communities:
   - name: Lab 1
     id: lab1
-    contact: lab1.kfj
+    contactId: lab1.kfj
     sites:
       - id: lab1.site1 
         name: Lab Site 1
+        type: Network Headend
+        devices:
+          - id: lab1.site1.rt1
+            name: Lab Site 1 Router 1
+            type: router
   
   - name: Core 1
     id: core1
-    contact: core1.hello
+    contactId: core1.hello
     sites:
       - id: core1.site1 
         name: Core Site 1
-
-networks:
-  - prefix: 1.1.1.0/24
-    description: HelloWorld
-    contactId: net.test
-    circuit:
-      id: core.lab1
-    networks:
-      - prefix: 1.1.1.0/30
-        description:  HelloWorld2
+        type: Network Headend
+        devices:
+          - id: core1.site1.rt1
+            name: Core 1 Site 1 Network Headend Router 1
 
 circuits:
   - id: core.lab1
-    sideA:
-      id: circuit1
-    sideZ:
-      id: circuit2
+    sideAID: circuit1
+    sideZID: circuit2
+    speed: 10M
 
 circuitLocations:
   - id: circuit1
     address: lab1 street 1
-    communuity: lab1
+    communuityId: lab1
     provider: Core Provider
     demarcSpeed: 1G
 
   - id: circuit2
     address: Core Site 1, Street 5859
-    communuity: core1
+    communuityId: core1
     demarcSpeed: 10G
     provider: Core Provider
 
 contacts:
   - id: lab1.kfj
     name: Kristian Jones
+
   - id: core1.hello
     name: Hello World
+
   - id: net.test
-    name: HelloTest
\ No newline at end of file
+    name: HelloTest
+
+  - id: thirdparty.core
+    name: Third Party Provider 1
+
+networks:
+  - prefix: 1.1.1.0/24
+    description: HelloWorld
+    contactId: net.test
+    circuitId: core.lab1
+    networks:
+      - prefix: 1.1.1.0/30
+        contactId: thirdparty.core
+        description: HelloWorld2
\ No newline at end of file
diff --git a/src/Modules/IPAM/IPAM.test.ts b/src/Modules/IPAM/IPAM.test.ts
new file mode 100644
index 0000000..d37f3f1
--- /dev/null
+++ b/src/Modules/IPAM/IPAM.test.ts
@@ -0,0 +1,122 @@
+// src/Modules/IPAM/IPAM.test.ts
+import { TestSuite } from '@k-foss/ts-estests';
+import { deepStrictEqual, rejects } from 'assert';
+import { resolve } from 'path';
+import Container from 'typedi';
+import { fileURLToPath } from 'url';
+import { IPAMController } from './IPAMController';
+
+export class IPAMSuite extends TestSuite {
+  public testName = 'IPAM Test Suite';
+
+  public async test(): Promise {
+    const ipamValidContainer1 = Container.of('IPAMValid1');
+
+    const ipamValidController = IPAMController.createIPAM({
+      container: ipamValidContainer1,
+    });
+
+    const ipamValidFixture1Path = resolve(
+      fileURLToPath(import.meta.url),
+      '../fixtures/ValidFile1.yaml',
+    );
+
+    console.log('Loading?');
+
+    /**
+     * Valid Config 1
+     *
+     * 1 Root Network
+     * 1 Child Network
+     *
+     * 1 Contact
+     *
+     * 2 Circuit Locations
+     *
+     * 1 Circuit
+     *
+     * 1 Community
+     * 2 Sites under Community
+     */
+    const validConfig1 = await ipamValidController.loadIPAM(
+      ipamValidFixture1Path,
+    );
+
+    deepStrictEqual(
+      typeof validConfig1 === 'undefined',
+      false,
+      'typeof validConfig1 === undefined === false',
+    );
+
+    deepStrictEqual(
+      validConfig1.networks.length,
+      2,
+      `validConfig1.networks.length === 2`,
+    );
+
+    /**
+     * Invalid YAML #1 - Single Invalid Device ID
+     */
+    const ipamInvalidFixture1Path = resolve(
+      fileURLToPath(import.meta.url),
+      '../fixtures/InvalidFile1.yaml',
+    );
+
+    const ipamInvalidContainer1 = Container.of('IPAMInvalid1');
+    const invalidIPAMController1 = IPAMController.createIPAM({
+      container: ipamInvalidContainer1,
+    });
+
+    await rejects(
+      invalidIPAMController1.loadIPAM(ipamInvalidFixture1Path),
+      [
+        `${ipamInvalidFixture1Path}: line 50, Error - Sitedevice with ID (tor.c1.rt0) does not exist! (validId)`,
+      ],
+      'Invalid Device ID Throws',
+    );
+
+    /**
+     * Invalid YAML #2 - Two Invalid Device IDs
+     */
+    const ipamInvalidFixture2Path = resolve(
+      fileURLToPath(import.meta.url),
+      '../fixtures/InvalidFile2.yaml',
+    );
+
+    const ipamInvalidContainer2 = Container.of('IPAMInvalid2');
+    const invalidIPAMController2 = IPAMController.createIPAM({
+      container: ipamInvalidContainer2,
+    });
+
+    await rejects(
+      invalidIPAMController2.loadIPAM(ipamInvalidFixture2Path),
+      [
+        `${ipamInvalidFixture2Path}: line 50, Error - Sitedevice with ID (tor.c1.rt0) does not exist! (validId)`,
+        `${ipamInvalidFixture2Path}: line 54, Error - Sitedevice with ID (tor.c2.rt4) does not exist! (validId)`,
+      ],
+      'Invalid Device ID Throws',
+    );
+
+    /**
+     * Invalid YAML #3 - One Invalid Device ID and One Invalid Subnet prefix
+     */
+    const ipamInvalidFixture3Path = resolve(
+      fileURLToPath(import.meta.url),
+      '../fixtures/InvalidFile3.yaml',
+    );
+
+    const ipamInvalidContainer3 = Container.of('IPAMInvalid3');
+    const invalidIPAMController3 = IPAMController.createIPAM({
+      container: ipamInvalidContainer3,
+    });
+
+    await rejects(
+      invalidIPAMController3.loadIPAM(ipamInvalidFixture3Path),
+      [
+        `${ipamInvalidFixture3Path}: line 44, Error - Prefix (1.0.0.0/23) is not a valid parent IPv4 Prefix of this network! (ValidSubnet)`,
+        `${ipamInvalidFixture3Path}: line 50, Error - Sitedevice with ID (tor.c1.rt0) does not exist! (validId)`,
+      ],
+      'Invalid Device ID & Invalid Network Prefix Throws',
+    );
+  }
+}
diff --git a/src/Modules/IPAM/IPAM.ts b/src/Modules/IPAM/IPAM.ts
index 6b8641e..d16e092 100644
--- a/src/Modules/IPAM/IPAM.ts
+++ b/src/Modules/IPAM/IPAM.ts
@@ -1,25 +1,144 @@
 // src/Modules/IPAM/IPAM.ts
-
-import { Service } from 'typedi';
+import { plainToClass, Transform, Type } from 'class-transformer';
+import { ValidateNested } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Container, Service } from 'typedi';
+import { contextToken } from '../../Library/Context';
+import { logger, LogMode } from '../../Library/Logger';
+import { getManyContainer, setContainer } from '../../Utils/Containers';
 import { Circuit } from '../Circuits/Circuit';
 import { CircuitLocation } from '../Circuits/CircuitLocation';
+import { Community } from '../Communities/Community';
 import { Contact } from '../Contacts/Contact';
 import { Network } from '../Networks/Network';
-import { Community } from '../Communities/Community';
 
+export function processNetworks(
+  networks: Network[],
+  parentNetwork?: Network,
+): void[] {
+  return networks.flatMap((network) => {
+    if (network.circuitId) {
+      Container.set({
+        id: `circuitNetworks-${network.circuitId}`,
+        multiple: true,
+        value: network.prefix,
+      });
+    }
+
+    if (parentNetwork) {
+      Container.set({
+        id: `networks-${parentNetwork.prefix}`,
+        multiple: true,
+        value: network.prefix,
+      });
+    }
+
+    return setContainer('NETWORK', network.prefix, network);
+  });
+}
+
+@JSONSchema({
+  title: 'IPAM File',
+  description: 'IPAM',
+  additionalProperties: false,
+})
 @Service()
 export class IPAM {
+  @ValidateNested({ each: true })
+  @Transform((items: Contact[]) => {
+    logger.log(LogMode.DEBUG, `Transforming Contacts from IPAM`);
+
+    items.map((item) =>
+      setContainer(
+        'CONTACT',
+        item.id,
+        plainToClass(Contact, item),
+        Container.get(contextToken).container,
+      ),
+    );
+
+    return getManyContainer('CONTACT', Container.get(contextToken).container);
+  })
+  @Type(() => Contact)
   public contacts: Contact[];
 
+  @ValidateNested({ each: true, always: true })
+  @Transform(
+    (items: Community[]) => {
+      logger.log(LogMode.DEBUG, `Transforming Communities from IPAM`);
+      items.map((item) =>
+        setContainer(
+          'COMMUNITY',
+          item.id,
+          item,
+          Container.get(contextToken).container,
+        ),
+      );
+
+      return getManyContainer(
+        'COMMUNITY',
+        Container.get(contextToken).container,
+      );
+    },
+    {
+      toClassOnly: true,
+    },
+  )
+  @Type(() => Community)
   public communities: Community[];
 
+  @ValidateNested({ each: true })
+  @Transform((items: CircuitLocation[]) => {
+    logger.log(LogMode.DEBUG, `Transforming Circuit Locations from IPAM`);
+    items.map((item) =>
+      setContainer(
+        'CIRCUITLOCATION',
+        item.id,
+        item,
+        Container.get(contextToken).container,
+      ),
+    );
+
+    return getManyContainer(
+      'CIRCUITLOCATION',
+      Container.get(contextToken).container,
+    );
+  }, {})
+  @Type(() => CircuitLocation)
   public circuitLocations: CircuitLocation[];
 
+  @ValidateNested({ each: true })
+  @Transform((items: Circuit[]) => {
+    logger.log(LogMode.DEBUG, `Transforming Circuits from IPAM`);
+    items.map((item) =>
+      setContainer(
+        'CIRCUIT',
+        item.id,
+        item,
+        Container.get(contextToken).container,
+      ),
+    );
+
+    return getManyContainer('CIRCUIT', Container.get(contextToken).container);
+  }, {})
+  @Type(() => Circuit)
   public circuits: Circuit[];
 
-  public networks: Network[];
+  @ValidateNested({ each: true })
+  @Transform((items: Network[]) => {
+    logger.log(LogMode.DEBUG, `Transforming Networks from IPAM`);
+
+    items.map((item) =>
+      setContainer(
+        'NETWORK',
+        item.prefix,
+        item,
+        Container.get(contextToken).container,
+      ),
+    );
 
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
+    return getManyContainer('NETWORK', Container.get(contextToken).container);
+  }, {})
+  @Type(() => Network)
+  public networks: Network[];
 }
diff --git a/src/Modules/IPAM/IPAMConfig.gen.ts b/src/Modules/IPAM/IPAMConfig.gen.ts
deleted file mode 100644
index 95b9235..0000000
--- a/src/Modules/IPAM/IPAMConfig.gen.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-/* tslint:disable */
-/**
- * This file was automatically generated by json-schema-to-typescript.
- * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
- * and run json-schema-to-typescript to regenerate this file.
- */
-
-export type NetworkDeviceType =
-  | "router"
-  | "switch"
-  | "access-point"
-  | "server"
-  | "modem"
-  | "firewall"
-  | "UPS"
-  | "cell-vpn"
-  | "cell-gw";
-/**
- * Unique Identifier for referencing Contact
- */
-export type ContactId = string;
-
-/**
- * IPAM Configuration File
- */
-export interface IPAM {
-  communities: Community[];
-  /**
-   * Circuits
-   */
-  circuits: Circuit[];
-  /**
-   * External Circuits
-   */
-  circuitLocations: CircuitLocation[];
-  /**
-   * Contact Information
-   */
-  contacts: Contact[];
-  /**
-   * Networks
-   */
-  networks: Network[];
-}
-/**
- * Community
- */
-export interface Community {
-  /**
-   * Community Contact ID
-   */
-  contact?: string;
-  /**
-   * Community Friendly Name
-   */
-  name: string;
-  /**
-   * Short form community code
-   */
-  id: string;
-  sites: CommunitySite[];
-}
-/**
- * Community Site
- */
-export interface CommunitySite {
-  /**
-   * Site short id
-   */
-  id: string;
-  name: string;
-  type?:
-    | "Network Headend"
-    | "Community Center"
-    | "Health Center"
-    | "Cell Tower"
-    | "Colocation"
-    | "Band Office"
-    | "School"
-    | "Lake HeadU"
-    | "KO Office"
-    | "Tower";
-  devices?: Device[];
-}
-/**
- * Network Device
- */
-export interface Device {
-  /**
-   * Chained ID
-   */
-  id: string;
-  /**
-   * Friendly name
-   */
-  name: string;
-  type?: NetworkDeviceType;
-}
-/**
- * Community Circuit
- */
-export interface Circuit {
-  /**
-   * Circuit ID
-   */
-  id: string;
-  sideA: CircuitSide;
-  sideZ: CircuitSide;
-  speed?: string;
-}
-export interface CircuitSide {
-  /**
-   * Circuit Location Id
-   */
-  id: string;
-}
-/**
- * Traditional external circuits
- */
-export interface CircuitLocation {
-  /**
-   * External circuit id
-   */
-  id?: string;
-  /**
-   * External circuit provider
-   */
-  provider?: string;
-  /**
-   * Community ID
-   */
-  communuity?: string;
-  /**
-   * Address provided to external provider
-   */
-  address?: string;
-  demarcSpeed?: "10M" | "100M" | "200M" | "300M" | "500M" | "1G" | "5G" | "10G";
-}
-/**
- * Community Contact
- */
-export interface Contact {
-  id: ContactId;
-  /**
-   * Contact Full Name
-   */
-  name: string;
-}
-/**
- * Network
- */
-export interface Network {
-  /**
-   * Network Prefix
-   */
-  prefix?: string;
-  description?: string;
-  circuit?: Networkcircuit;
-  nsServers?: string[];
-  /**
-   * Network Type
-   */
-  type?: "UNALLOCATED" | "EXTERNAL";
-  contactId?: ContactId;
-  hosts?: NetworkHost[];
-  ranges?: NetworkRange[];
-  /**
-   * Children Networks
-   */
-  networks?: Network[];
-}
-/**
- * NetworkCircuit
- */
-export interface Networkcircuit {
-  /**
-   * Circuit Id
-   */
-  id: string;
-  /**
-   * Circuit Speed
-   */
-  speed?: string;
-}
-/**
- * Indivual Network host
- */
-export interface NetworkHost {
-  /**
-   * Host IP Address
-   */
-  ip: string;
-  /**
-   * Hostname for reverse DNS creation
-   */
-  hostname?: string;
-  contactId?: ContactId;
-  description?: string;
-  device?: NetworkDeviceLink;
-}
-/**
- * Link a Network to a device
- */
-export interface NetworkDeviceLink {
-  /**
-   * Device id
-   */
-  id: string;
-  /**
-   * Device interface
-   */
-  interface?: string;
-}
-/**
- * Network Range
- */
-export interface NetworkRange {
-  /**
-   * Start IP for the range
-   */
-  start: string;
-  /**
-   * End IP for the range
-   */
-  end: string;
-  description?: string;
-  type?: "DHCP" | "RESERVED" | "STATIC" | "FREE" | "unallocated";
-}
diff --git a/src/Modules/IPAM/IPAMConfigController.ts b/src/Modules/IPAM/IPAMConfigController.ts
deleted file mode 100644
index 7e22682..0000000
--- a/src/Modules/IPAM/IPAMConfigController.ts
+++ /dev/null
@@ -1,226 +0,0 @@
-// src/Modules/Communities/CommunityConfigController.ts
-import { PathLike } from 'fs';
-import { readFile } from 'fs/promises';
-import { load } from 'js-yaml';
-import Container, { Service } from 'typedi';
-import { logger, LogMode } from '../../Library/Logger';
-import { createContainerName, setContainer } from '../../Utils/Containers';
-import { isObjectType } from '../../Utils/isTypes';
-import { Circuit } from '../Circuits/Circuit';
-import { CircuitLocation } from '../Circuits/CircuitLocation';
-import { Site } from '../Sites/Site';
-import { Contact } from '../Contacts/Contact';
-import { NetworkDevice } from '../NetworkDevices/NetworkDevice';
-import { Network } from '../Networks/Network';
-import { NetworkHost } from '../Networks/NetworkHost';
-import { Community } from '../Communities/Community';
-import { IPAM } from './IPAM';
-import {
-  IPAM as IPAMType,
-  Community as IPAMCommunity,
-  Contact as IPAMContact,
-  CommunitySite as IPAMCommunitySite,
-  Device as IPAMDevice,
-  Circuit as IPAMCircuit,
-  CircuitLocation as IPAMCircuitLocation,
-  Network as IPAMNetwork,
-  NetworkHost as IPAMNetworkHost,
-} from './IPAMConfig.gen';
-
-@Service()
-export class IPAMConfigController {
-  public processContacts(contacts: IPAMContact[]): Contact[] {
-    return contacts.map((contactValues) => {
-      const contact = new Contact(contactValues);
-
-      setContainer('CONTACT', contact.id, contact);
-
-      return contact;
-    });
-  }
-
-  public processSiteDevices(devices: IPAMDevice[]): NetworkDevice[] {
-    return devices.map((deviceValues) => {
-      const device = new NetworkDevice(deviceValues);
-
-      setContainer('SITE_DEVICE', device.id, device);
-
-      return device;
-    });
-  }
-
-  public processSites(sites: IPAMCommunitySite[]): Site[] {
-    return sites.map((communitySiteValues) => {
-      const communitySite = new Site({
-        ...communitySiteValues,
-        devices:
-          typeof communitySiteValues.devices !== 'undefined'
-            ? this.processSiteDevices(communitySiteValues.devices)
-            : [],
-      });
-
-      setContainer('SITE', communitySite.id, communitySite);
-
-      return communitySite;
-    });
-  }
-
-  public processCommunities(communities: IPAMCommunity[]): Community[] {
-    return communities.map(
-      ({ sites, contact: contactId, ...communityValues }) => {
-        const community = new Community({
-          ...communityValues,
-          contactId,
-          sites: this.processSites(sites),
-        });
-
-        setContainer('COMMUNITY', community.id, community);
-
-        return community;
-      },
-    );
-  }
-
-  public processCircuitLocations(
-    circuitLocations: IPAMCircuitLocation[],
-  ): CircuitLocation[] {
-    return circuitLocations.map(
-      ({ communuity, ...communityLocationValues }) => {
-        const circuitLocation = new CircuitLocation({
-          communuityId: communuity,
-          ...communityLocationValues,
-        });
-
-        setContainer('CIRCUIT_LOCATION', circuitLocation.id, circuitLocation);
-
-        return circuitLocation;
-      },
-    );
-  }
-
-  public processCircuits(circuits: IPAMCircuit[]): Circuit[] {
-    return circuits.map((circuitValues) => {
-      const circuit = new Circuit(circuitValues);
-
-      setContainer('CIRCUIT', circuit.id, circuit);
-
-      return circuit;
-    });
-  }
-
-  public processNetworkHosts(
-    networkHosts: IPAMNetworkHost[],
-    parentNetwork: Network,
-  ): NetworkHost[] {
-    return networkHosts.map((networkHostValue) => {
-      const networkHost = new NetworkHost({
-        ...networkHostValue,
-        parentNetworkId: parentNetwork.prefix,
-      });
-
-      Container.set({
-        id: `networkHost-${parentNetwork.prefix}`,
-        multiple: true,
-        value: networkHost,
-      });
-
-      setContainer('NETWORK_HOST', networkHost.ip, networkHost);
-
-      return networkHost;
-    });
-  }
-
-  public processNetworks(
-    networks: IPAMNetwork[],
-    parentNetwork?: Network,
-  ): Network[] {
-    return networks.flatMap(
-      ({
-        circuit,
-        networks: subNetworksValues,
-        hosts: hostsValue,
-        ...networkValues
-      }) => {
-        const network = new Network({
-          circuitId: circuit?.id,
-          parentNetworkId: parentNetwork?.prefix,
-          ...networkValues,
-        });
-
-        if (network.circuitId) {
-          Container.set({
-            id: `circuitNetworks-${network.circuitId}`,
-            multiple: true,
-            value: () =>
-              Container.get(createContainerName('NETWORK', network.prefix)),
-          });
-        }
-
-        const subNetworks = subNetworksValues
-          ? this.processNetworks(subNetworksValues, network)
-          : [];
-
-        if (parentNetwork) {
-          Container.set({
-            id: `networks-${parentNetwork.prefix}`,
-            multiple: true,
-            value: network,
-          });
-        }
-
-        if (hostsValue) {
-          this.processNetworkHosts(hostsValue, network);
-        }
-
-        setContainer('NETWORK', network.prefix, network);
-
-        return [network, ...subNetworks];
-      },
-    );
-  }
-
-  /**
-   * Load the configured firewalls configuration file from disk, parse the YAML and load into the class
-   */
-  public async loadFile(filePath?: PathLike): Promise {
-    const ipamConfigFilePath = filePath || 'ipam.yml';
-
-    const ipamFile = await readFile(ipamConfigFilePath);
-
-    const ipamConfigFile = load(ipamFile.toString());
-
-    if (isObjectType(ipamConfigFile, 'communities')) {
-      logger.log(
-        LogMode.INFO,
-        'Loaded Communities Configuration File',
-        ipamConfigFilePath,
-      );
-
-      logger.log(LogMode.DEBUG, `IPAMConfig: `, ipamConfigFile);
-
-      const contacts = this.processContacts(ipamConfigFile.contacts);
-      const communities = this.processCommunities(ipamConfigFile.communities);
-
-      const circuitLocations = this.processCircuitLocations(
-        ipamConfigFile.circuitLocations,
-      );
-
-      const circuits = this.processCircuits(ipamConfigFile.circuits);
-      const networks = this.processNetworks(ipamConfigFile.networks);
-
-      Container.set('networks', networks);
-
-      return new IPAM({
-        circuitLocations,
-        circuits,
-        communities,
-        contacts,
-        networks,
-      });
-    }
-
-    throw new Error('Invalid IPAM configuration file');
-  }
-}
-
-export const ipamConfigController = new IPAMConfigController();
diff --git a/src/Modules/IPAM/IPAMConfigSchema.ts b/src/Modules/IPAM/IPAMConfigSchema.ts
deleted file mode 100644
index c9026d5..0000000
--- a/src/Modules/IPAM/IPAMConfigSchema.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-// src/Modules/Communities/CommunityConfigSchema.ts
-import jsonSchema from 'fluent-json-schema';
-import { circuitLocationSchema } from '../CommunityCircuits/CircuitLocationSchema';
-import { circuitSchema } from '../Circuits/CircuitSchema';
-import { contactSchema } from '../Contacts/ContactSchema';
-import { siteSchema } from '../Sites/SiteSchema';
-import { networkCircuitSchema } from '../Networks/NetworkCircuitSchema';
-import { networkSchema } from '../Networks/NetworkSchema';
-import { networkDeviceConfigSchema } from '../NetworkDevices/NetworkDeviceConfigSchema';
-import { NetworkDeviceInterfaceType } from '../NetworkDevices/NetworkDeviceInterfaceType';
-import { networkDeviceLinkSchema } from '../NetworkDevices/NetworkDeviceLinkSchema';
-import { NetworkDeviceType } from '../NetworkDevices/NetworkDeviceType';
-import { communitySchema } from '../Communities/CommunitySchema';
-import { circuitSideSchema } from '../Circuits/CircuitSideSchema';
-import { networkHostSchema } from '../Networks/NetworkHostSchema';
-import { networkRangeSchema } from '../Networks/NetworkRangeSchema';
-
-export const communityConfigSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .description('IPAM Configuration File')
-  .definition('community', communitySchema)
-  .definition('communitySite', siteSchema)
-  .definition('contact', contactSchema)
-  .definition(
-    'contactId',
-    jsonSchema
-      .string()
-      .description('Unique Identifier for referencing Contact'),
-  )
-  .definition('device', networkDeviceConfigSchema)
-  .definition('networkcircuit', networkCircuitSchema)
-  .definition('networkDeviceLink', networkDeviceLinkSchema)
-  .definition('circuitLocation', circuitLocationSchema)
-  .definition('circuit', circuitSchema)
-  .definition('circuitSide', circuitSideSchema)
-  .definition('network', networkSchema)
-  .definition('networkHost', networkHostSchema)
-  .definition('networkRange', networkRangeSchema)
-  .definition(
-    'networkDeviceType',
-    jsonSchema.string().enum(Object.values(NetworkDeviceType)),
-  )
-  .definition(
-    'networkDeviceInterfaceType',
-    jsonSchema.string().enum(Object.values(NetworkDeviceInterfaceType)),
-  )
-  .prop(
-    'communities',
-    jsonSchema
-      .array()
-      .items(jsonSchema.ref('#/definitions/community'))
-      .required(),
-  )
-  .prop(
-    'circuits',
-    jsonSchema
-      .array()
-      .items(jsonSchema.ref('#/definitions/circuit'))
-      .uniqueItems(true)
-      .required()
-      .description('Circuits'),
-  )
-  .prop(
-    'circuitLocations',
-    jsonSchema
-      .array()
-      .items(jsonSchema.ref('#/definitions/circuitLocation'))
-      .uniqueItems(true)
-      .required()
-      .description('External Circuits'),
-  )
-  .prop(
-    'contacts',
-    jsonSchema
-      .array()
-      .items(jsonSchema.ref('#/definitions/contact'))
-      .uniqueItems(true)
-      .required()
-      .description('Contact Information'),
-  )
-  .prop(
-    'networks',
-    jsonSchema
-      .array()
-      .items(jsonSchema.ref('#/definitions/network'))
-      .uniqueItems(true)
-      .required()
-      .description('Networks'),
-  );
diff --git a/src/Modules/IPAM/IPAMController.ts b/src/Modules/IPAM/IPAMController.ts
new file mode 100644
index 0000000..7533aa5
--- /dev/null
+++ b/src/Modules/IPAM/IPAMController.ts
@@ -0,0 +1,196 @@
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+// src/Modules/IPAM/IPAMController.ts
+import Ajv, { ValidateFunction } from 'ajv';
+import { validationMetadatasToSchemas } from 'class-validator-jsonschema';
+import { PathLike } from 'fs';
+import { readFile, writeFile } from 'fs/promises';
+import { resolve } from 'path';
+import { Inject, Service } from 'typedi';
+import { fileURLToPath } from 'url';
+import { logger, LogMode } from '../../Library/Logger';
+import { IPAM } from './IPAM';
+import { load } from 'js-yaml';
+import { defaultMetadataStorage } from 'class-transformer/storage';
+import { plainToClass } from 'class-transformer';
+import { validateOrReject, ValidationError } from 'class-validator';
+import { getIDField, isIPAMType, ValueTypes } from '../../Utils/Types';
+import { isValidationErrors } from '../../Utils/ValidatorErrors';
+import { contextToken, createContext } from '../../Library/Context';
+import type { Context } from '../../Library/Context';
+interface FieldContext {
+  locateField: boolean;
+}
+
+function isFieldContext(
+  context: FieldContext | Record,
+): context is FieldContext {
+  return 'locateField' in context;
+}
+
+@Service()
+export class IPAMController {
+  @Inject(contextToken)
+  public context: Context;
+
+  public static createIPAM(initialContext?: Context): IPAMController {
+    const context = createContext(initialContext);
+
+    return context.container.get(IPAMController);
+  }
+
+  /**
+   * Create the AJV JSON Schema from `IPAM.ts` class.
+   *
+   * @returns Promise that resovles to the validate function for `IPAM`
+   */
+  public async createSchema(): Promise> {
+    logger.log(
+      LogMode.DEBUG,
+      `IPAMController.createSchema() Creating JSON Schema.`,
+    );
+
+    logger.log(
+      LogMode.DEBUG,
+      `ConfigController.createSchema() Dynamically importing ./ConfigSchema`,
+    );
+    await Promise.all([import('./IPAM')]);
+
+    const { IPAM, ...schemas } = validationMetadatasToSchemas({
+      classTransformerMetadataStorage: defaultMetadataStorage,
+    });
+
+    const coreSchema = {
+      $schema: 'http://json-schema.org/draft-07/schema#',
+      definitions: schemas,
+      $id: 'IPAM',
+      ...IPAM,
+    };
+
+    const ajv = new Ajv();
+
+    return ajv.compile(coreSchema, true);
+  }
+
+  /**
+   * Load JSON Schema and save `IPAM.json` to Schemas folder.
+   *
+   * @returns Promise that resolves once the file has been saved.
+   */
+  public async saveSchema(): Promise {
+    const schema = await this.createSchema();
+
+    const schemaFilePath = resolve(
+      fileURLToPath(import.meta.url),
+      '../../../../schemas/IPAM.json',
+    );
+
+    return writeFile(schemaFilePath, JSON.stringify(schema.schema));
+  }
+
+  /**
+   * Load an `IPAM.yaml` validate the file agaisnt the JSON Schema, and run `class-validator` and `class-transformer`
+   * @param ipamPath File path to IPAM File @default `IPAM.yaml`
+   *
+   * @returns Promise resolving to processed and validated IPAM Class.
+   */
+  public async loadIPAM(ipamPath?: PathLike): Promise {
+    const filePath = ipamPath ?? 'IPAM.yaml';
+
+    const ipamValidator = await this.createSchema();
+
+    const ipamFile = await readFile(filePath);
+    const ipamString = ipamFile.toString();
+
+    const ipamYAML = load(ipamString);
+
+    const errors: Set = new Set();
+
+    if (ipamValidator(ipamYAML)) {
+      try {
+        const transformed = plainToClass(IPAM, ipamYAML, {
+          strategy: 'exposeAll',
+        });
+
+        logger.log(LogMode.DEBUG, `Stuff: `, transformed);
+
+        await validateOrReject(transformed);
+
+        return transformed;
+      } catch (errs) {
+        logger.log(LogMode.DEBUG, `loadIPAM() caught error: `, errs);
+
+        if (isValidationErrors(errs)) {
+          function flat(
+            r: ValidationError[],
+            currentValue: ValidationError,
+          ): ValidationError[] {
+            if (currentValue.children.length > 0) {
+              return currentValue.children.reduce(flat, r);
+            }
+
+            r.push(currentValue);
+            return r;
+          }
+
+          const newCoreValidationError = errs.reduce(flat, []);
+
+          for (const validationError of newCoreValidationError) {
+            const target = validationError.target as ValueTypes[keyof ValueTypes];
+
+            if (isIPAMType(target)) {
+              const [idFieldName, idFieldValue] = getIDField(target);
+
+              let regex: RegExp;
+              if (validationError.contexts) {
+                const contextCore = Object.values(validationError.contexts)[0];
+
+                if (isFieldContext(contextCore)) {
+                  if (contextCore?.locateField === false) {
+                    regex = new RegExp(`${idFieldName}: ${idFieldValue}`);
+                  }
+                }
+              }
+
+              regex ??= new RegExp(
+                `((?<=(?(?:${idFieldName}: ${idFieldValue})\\s+))\\s+(?<${
+                  validationError.property
+                }>${validationError.property}: ${
+                  validationError.value as string
+                }))|((?<${validationError.property}Second>${
+                  validationError.property
+                }: ${validationError.value as string})(?=\\k))`,
+                `gms`,
+              );
+
+              const match = regex.exec(ipamString);
+
+              const line = match?.input?.substr(0, match.index).match(/\n/g)
+                ?.length;
+
+              if (typeof line === 'number') {
+                const [key, message] = Object.entries(
+                  validationError.constraints as { [key: string]: string },
+                )[0];
+
+                errors.add(
+                  `${filePath.toString()}: line ${
+                    line + 1
+                  }, Error - ${message} (${key})`,
+                );
+              }
+
+              logger.log(LogMode.DEBUG, `loadIPAM() className: `);
+            }
+          }
+        }
+      }
+    } else {
+      logger.log(LogMode.WARN, `Invalid IPAM`);
+
+      logger.log(LogMode.DEBUG, `TODO: Handle processing invalid IPAM`);
+    }
+
+    // eslint-disable-next-line no-throw-literal
+    throw Array.from(errors);
+  }
+}
diff --git a/src/Modules/IPAM/fixtures/InvalidFile1.yaml b/src/Modules/IPAM/fixtures/InvalidFile1.yaml
new file mode 100644
index 0000000..78b75d8
--- /dev/null
+++ b/src/Modules/IPAM/fixtures/InvalidFile1.yaml
@@ -0,0 +1,55 @@
+communities:
+  - name: Toronto
+    id: tor
+    contactId: tor.todo1
+    sites:
+      - id: tor.c1
+        name: Toronto Cabniet 12
+        devices:
+          - id: tor.c1.rt1
+            name: Torotno Cabinet 1 Router 1
+
+      - id: tor.c2
+        name: Toronto Cabniet 2
+        devices:
+          - id: tor.c2.rt0
+            name: Torotno Cabinet 2 Router 1
+
+circuits:
+  - id: tor.clink
+    sideAID: tor.c1
+    sideZID: tor.c2
+    speed: 10G
+
+circuitLocations:
+  - id: tor.c1
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+  - id: tor.c2
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+contacts:
+  - id: tor.todo1
+    name: TODO
+
+networks:
+  - prefix: 1.0.0.0/23
+    networks:
+      - prefix: 1.0.0.0/30
+        description: Toronto Cabniet P2P
+        hosts:
+          - ip: 1.0.0.1
+            description: Toronto Cabniet 1
+            contactId: tor.todo1
+            deviceId: tor.c1.rt0
+            deviceInterface: TenGigE0/0/0/1
+          - ip: 1.0.0.2
+            description: Toronto Cabniet 2
+            deviceId: tor.c2.rt0
+            deviceInterface: TenGigE0/0/0/2
diff --git a/src/Modules/IPAM/fixtures/InvalidFile2.yaml b/src/Modules/IPAM/fixtures/InvalidFile2.yaml
new file mode 100644
index 0000000..7b62471
--- /dev/null
+++ b/src/Modules/IPAM/fixtures/InvalidFile2.yaml
@@ -0,0 +1,55 @@
+communities:
+  - name: Toronto
+    id: tor
+    contactId: tor.todo1
+    sites:
+      - id: tor.c1
+        name: Toronto Cabniet 12
+        devices:
+          - id: tor.c1.rt1
+            name: Torotno Cabinet 1 Router 1
+
+      - id: tor.c2
+        name: Toronto Cabniet 2
+        devices:
+          - id: tor.c2.rt1
+            name: Torotno Cabinet 2 Router 1
+
+circuits:
+  - id: tor.clink
+    sideAID: tor.c1
+    sideZID: tor.c2
+    speed: 10G
+
+circuitLocations:
+  - id: tor.c1
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+  - id: tor.c2
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+contacts:
+  - id: tor.todo1
+    name: TODO
+
+networks:
+  - prefix: 1.0.0.0/23
+    networks:
+      - prefix: 1.0.0.0/30
+        description: Toronto Cabniet P2P
+        hosts:
+          - ip: 1.0.0.1
+            description: Toronto Cabniet 1
+            contactId: tor.todo1
+            deviceId: tor.c1.rt0
+            deviceInterface: TenGigE0/0/0/1
+          - ip: 1.0.0.2
+            description: Toronto Cabniet 2
+            deviceId: tor.c2.rt4
+            deviceInterface: TenGigE0/0/0/2
diff --git a/src/Modules/IPAM/fixtures/InvalidFile3.yaml b/src/Modules/IPAM/fixtures/InvalidFile3.yaml
new file mode 100644
index 0000000..111cb56
--- /dev/null
+++ b/src/Modules/IPAM/fixtures/InvalidFile3.yaml
@@ -0,0 +1,55 @@
+communities:
+  - name: Toronto
+    id: tor
+    contactId: tor.todo1
+    sites:
+      - id: tor.c1
+        name: Toronto Cabniet 12
+        devices:
+          - id: tor.c1.rt1
+            name: Torotno Cabinet 1 Router 1
+
+      - id: tor.c2
+        name: Toronto Cabniet 2
+        devices:
+          - id: tor.c2.rt0
+            name: Torotno Cabinet 2 Router 1
+
+circuits:
+  - id: tor.clink
+    sideAID: tor.c1
+    sideZID: tor.c2
+    speed: 10G
+
+circuitLocations:
+  - id: tor.c1
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+  - id: tor.c2
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+contacts:
+  - id: tor.todo1
+    name: TODO
+
+networks:
+  - prefix: 1.0.0.0/23
+    networks:
+      - prefix: 1.0.0.0/20
+        description: Toronto Cabniet P2P
+        hosts:
+          - ip: 1.0.0.1
+            description: Toronto Cabniet 1
+            contactId: tor.todo1
+            deviceId: tor.c1.rt0
+            deviceInterface: TenGigE0/0/0/1
+          - ip: 1.0.0.2
+            description: Toronto Cabniet 2
+            deviceId: tor.c2.rt0
+            deviceInterface: TenGigE0/0/0/2
diff --git a/src/Modules/IPAM/fixtures/ValidFile1.yaml b/src/Modules/IPAM/fixtures/ValidFile1.yaml
new file mode 100644
index 0000000..dfee31f
--- /dev/null
+++ b/src/Modules/IPAM/fixtures/ValidFile1.yaml
@@ -0,0 +1,55 @@
+communities:
+  - name: Toronto
+    id: tor
+    contactId: tor.todo1
+    sites:
+      - id: tor.c1
+        name: Toronto Cabniet 12
+        devices:
+          - id: tor.c1.rt1
+            name: Torotno Cabinet 1 Router 1
+
+      - id: tor.c2
+        name: Toronto Cabniet 2
+        devices:
+          - id: tor.c2.rt1
+            name: Torotno Cabinet 2 Router 1
+
+circuits:
+  - id: tor.clink
+    sideAID: tor.c1
+    sideZID: tor.c2
+    speed: 10G
+
+circuitLocations:
+  - id: tor.c1
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+  - id: tor.c2
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+contacts:
+  - id: tor.todo1
+    name: TODO
+
+networks:
+  - prefix: 1.0.0.0/23
+    networks:
+      - prefix: 1.0.0.0/30
+        description: Toronto Cabniet P2P
+        hosts:
+          - ip: 1.0.0.1
+            description: Toronto Cabniet 1
+            contactId: tor.todo1
+            deviceId: tor.c1.rt1
+            deviceInterface: TenGigE0/0/0/1
+          - ip: 1.0.0.2
+            description: Toronto Cabniet 2
+            deviceId: tor.c2.rt1
+            deviceInterface: TenGigE0/0/0/2
diff --git a/src/Modules/NetworkDevices/NetworkDeviceConfigSchema.ts b/src/Modules/NetworkDevices/NetworkDeviceConfigSchema.ts
deleted file mode 100644
index 5757edd..0000000
--- a/src/Modules/NetworkDevices/NetworkDeviceConfigSchema.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// src/Modules/NetworkDevices/NetworkDeviceConfigSchema.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const networkDeviceConfigSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .id('#device')
-  .description('Network Device')
-  .prop('id', jsonSchema.string().description('Chained ID').required())
-  .prop('name', jsonSchema.string().description('Friendly name').required())
-  .prop('type', jsonSchema.ref('#/definitions/networkDeviceType'));
diff --git a/src/Modules/NetworkDevices/NetworkDeviceLinkSchema.ts b/src/Modules/NetworkDevices/NetworkDeviceLinkSchema.ts
deleted file mode 100644
index 05de11b..0000000
--- a/src/Modules/NetworkDevices/NetworkDeviceLinkSchema.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// src/Modules/Network/NetworkDeviceLink.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const networkDeviceLinkSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .description('Link a Network to a device')
-  .prop('id', jsonSchema.string().description('Device id').required())
-  .prop('interface', jsonSchema.string().description('Device interface'));
diff --git a/src/Modules/Networks/Network.test.ts b/src/Modules/Networks/Network.test.ts
new file mode 100644
index 0000000..f4e648f
--- /dev/null
+++ b/src/Modules/Networks/Network.test.ts
@@ -0,0 +1,129 @@
+// src/Modules/Networks/Network.test.ts
+import { TestSuite } from '@k-foss/ts-estests';
+import { IPAMController } from '../IPAM/IPAMController';
+import { resolve } from 'path';
+import { fileURLToPath } from 'url';
+import { deepStrictEqual } from 'assert';
+import { Address4 } from 'ip-address';
+
+export class NetworkTestSuite extends TestSuite {
+  public testName = 'Network Test Suite';
+
+  public async test(): Promise {
+    const ipamController = IPAMController.createIPAM();
+
+    const networkFixturePath = resolve(
+      fileURLToPath(import.meta.url),
+      '../fixtures/Networks.yaml',
+    );
+
+    console.log(`networkFixturePath: `, networkFixturePath);
+
+    const config = await ipamController.loadIPAM(networkFixturePath);
+
+    const networkCore = config.networks.find(
+      ({ prefix }) => prefix === '1.0.0.0/30',
+    );
+
+    deepStrictEqual(
+      networkCore?.prefix,
+      '1.0.0.0/30',
+      'networkCore?.prefix === 1.0.0.0/30',
+    );
+    deepStrictEqual(
+      networkCore?.description,
+      'Toronto Cabniet P2P',
+      'networkCore?.description === Toronto Cabniet P2P',
+    );
+
+    /**
+     * networkCore?.hosts[0]
+     */
+    deepStrictEqual(
+      networkCore?.hosts[0]?.ip,
+      '1.0.0.1',
+      'networkCore?.hosts[0]?.ip === 1.0.0.1',
+    );
+    deepStrictEqual(
+      networkCore?.hosts[0]?.description,
+      'Toronto Cabniet 1',
+      'networkCore?.hosts[0]?.description === Toronto Cabniet 1',
+    );
+    deepStrictEqual(
+      networkCore?.hosts[0]?.contactId,
+      'tor.todo1',
+      'networkCore?.hosts[0]?.contactId === tor.todo1',
+    );
+    deepStrictEqual(
+      networkCore?.hosts[0]?.deviceId,
+      'tor.c1.rt1',
+      'networkCore?.hosts[0]?.deviceId === tor.c1.rt1',
+    );
+    deepStrictEqual(
+      networkCore?.hosts[0]?.deviceInterface,
+      'TenGigE0/0/0/1',
+      'networkCore?.hosts[0]?.deviceInterface === TenGigE0/0/0/1',
+    );
+
+    /**
+     * networkCore?.hosts[1]
+     */
+    deepStrictEqual(
+      networkCore?.hosts[1]?.ip,
+      '1.0.0.2',
+      'networkCore?.hosts[1]?.ip === 1.0.0.2',
+    );
+    deepStrictEqual(
+      networkCore?.hosts[1]?.description,
+      'Toronto Cabniet 2',
+      'networkCore?.hosts[1]?.description === Toronto Cabniet 2',
+    );
+    deepStrictEqual(
+      networkCore?.hosts[1]?.contactId,
+      undefined,
+      'networkCore?.hosts[1]?.contactId === undefined',
+    );
+
+    deepStrictEqual(
+      networkCore?.hosts[1]?.deviceId,
+      'tor.c2.rt1',
+      'networkCore?.hosts[1]?.deviceId === tor.c2.rt1',
+    );
+    deepStrictEqual(
+      networkCore?.hosts[1]?.deviceInterface,
+      'TenGigE0/0/0/2',
+      'networkCore?.hosts[1]?.deviceInterface === TenGigE0/0/0/2',
+    );
+
+    /**
+     * networkCore?.IPv4
+     */
+
+    const IPv4 = networkCore?.IPv4;
+    const localIPv4 = new Address4('1.0.0.0/30');
+
+    deepStrictEqual(
+      IPv4.address,
+      localIPv4.address,
+      `networkCore?.IPv4.address === new Address4('1.0.0.0/30').address`,
+    );
+
+    deepStrictEqual(
+      IPv4.addressMinusSuffix,
+      localIPv4.addressMinusSuffix,
+      `networkCore?.IPv4.addressMinusSuffix === new Address4('1.0.0.0/30').addressMinusSuffix`,
+    );
+
+    deepStrictEqual(
+      IPv4.subnet,
+      localIPv4.subnet,
+      `networkCore?.IPv4.subnet === new Address4('1.0.0.0/30').subnet`,
+    );
+
+    deepStrictEqual(
+      IPv4.subnetMask,
+      localIPv4.subnetMask,
+      `networkCore?.IPv4.subnetMask === new Address4('1.0.0.0/30').subnetMask`,
+    );
+  }
+}
diff --git a/src/Modules/Networks/Network.ts b/src/Modules/Networks/Network.ts
index 7791f64..12d954a 100644
--- a/src/Modules/Networks/Network.ts
+++ b/src/Modules/Networks/Network.ts
@@ -1,17 +1,42 @@
 // src/Modules/Networks/Network.ts
-import Container, { Service } from 'typedi';
-import { createContainerName } from '../../Utils/Containers';
+import { Transform, Type } from 'class-transformer';
+import {
+  IsOptional,
+  IsString,
+  Validate,
+  ValidateNested,
+} from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Address4 } from 'ip-address';
+import { Container, Service } from 'typedi';
+import { contextToken } from '../../Library/Context';
+import { logger, LogMode } from '../../Library/Logger';
+import { createContainerName, setContainer } from '../../Utils/Containers';
+import { IsValidID } from '../../Utils/Validator';
 import { Circuit } from '../Circuits/Circuit';
 import { Contact } from '../Contacts/Contact';
-import { Network as IPAMNetwork } from '../IPAM/IPAMConfig.gen';
 import { NetworkHost } from './NetworkHost';
-import { Address4 } from 'ip-address';
+import { NetworkRange } from './NetworkRange';
+import { NetworkType } from './NetworkType';
+import { ValidPrefix, ValidSubnet } from './PrefixValidator';
 
+@JSONSchema({
+  title: 'Network',
+  description: 'Network object',
+  additionalProperties: false,
+  required: ['prefix'],
+})
 @Service()
-export class Network implements Omit {
+export class Network {
   /**
    * Network Prefix
    */
+
+  @IsString()
+  @Validate(ValidPrefix)
+  @JSONSchema({
+    description: 'Network Prefix',
+  })
   public prefix: string;
 
   public get IPv4(): Address4 {
@@ -21,44 +46,111 @@ export class Network implements Omit {
   /**
    * Friendly description
    */
-  public description: string;
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    description: 'Description for this network',
+  })
+  public description?: string;
 
-  /**
-   * Circuit Identifier
-   */
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    description: 'Usage/type for this network',
+    enum: Object.values(NetworkType),
+  })
+  public type: NetworkType;
+
+  @IsOptional()
+  @IsString()
+  @IsValidID('CIRCUIT')
+  @Transform((circuitId: string, network: Network) => {
+    logger.log(LogMode.DEBUG, `Transforming Circuit Ids from IPAM`);
+
+    Container.get(contextToken).container.set({
+      id: `circuitNetworks-${circuitId}`,
+      multiple: true,
+      value: network.prefix,
+    });
+
+    return circuitId;
+  })
+  @JSONSchema({
+    description: 'Reference Circuit ID',
+  })
   public circuitId?: string;
 
-  public get networks(): Network[] | undefined {
-    return Container.getMany(`networks-${this.prefix}`);
-  }
+  @IsOptional()
+  @ValidateNested({ each: true })
+  @Transform((networks: Network[], parentNetwork: Network) => {
+    logger.log(LogMode.DEBUG, `Transforming Subnetworks from IPAM`);
 
-  /**
-   * Unique Parent Network Id
-   */
+    return networks.map((item) => {
+      item.parentNetworkId = parentNetwork.prefix;
+
+      setContainer(
+        'NETWORK',
+        item.prefix,
+        item,
+        Container.get(contextToken).container,
+      );
+
+      return Container.get(contextToken).container.get(
+        createContainerName('NETWORK', item.prefix),
+      );
+    });
+  })
+  @Type(() => Network)
+  public networks: Network[];
+
+  @IsOptional()
+  @ValidateNested({ each: true })
+  @Type(() => NetworkRange)
+  public ranges: NetworkRange[];
+
+  @IsOptional()
+  @Validate(ValidSubnet, {
+    context: {
+      locateField: false,
+    },
+  })
   public parentNetworkId?: string;
 
   public get parentNetwork(): Network | undefined {
     if (this.parentNetworkId) {
-      return Container.get(
+      return Container.get(contextToken).container.get(
         createContainerName('NETWORK', this.parentNetworkId),
       );
     }
   }
 
-  public get hosts(): NetworkHost[] {
-    return Container.getMany(`networkHost-${this.prefix}`);
-  }
+  @IsOptional()
+  @ValidateNested({ each: true })
+  @Type(() => NetworkHost)
+  public hosts: NetworkHost[];
 
-  /**
-   * Contact Object Identifier
-   */
+  @IsOptional()
+  @IsString()
+  @IsValidID('CONTACT')
+  @JSONSchema({
+    description: 'Reference Contact ID',
+  })
   public contactId?: string;
 
-  public free?: boolean;
+  @IsOptional()
+  @IsString({
+    each: true,
+  })
+  @JSONSchema({
+    description: 'Authorative name server to forward reverse DNS requests to',
+  })
+  public nsServers: string[];
 
   public get contact(): Contact | undefined {
     if (this.contactId) {
-      return Container.get(createContainerName('CONTACT', this.contactId));
+      return Container.get(contextToken).container.get(
+        createContainerName('CONTACT', this.contactId),
+      );
     }
 
     return this.parentNetwork?.contact;
@@ -69,13 +161,11 @@ export class Network implements Omit {
    */
   public get circuit(): Circuit | undefined {
     if (this.circuitId) {
-      return Container.get(createContainerName('CIRCUIT', this.circuitId));
+      return Container.get(contextToken).container.get(
+        createContainerName('CIRCUIT', this.circuitId),
+      );
     }
 
     return this.parentNetwork?.circuit;
   }
-
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
 }
diff --git a/src/Modules/Networks/NetworkCircuitSchema.ts b/src/Modules/Networks/NetworkCircuitSchema.ts
deleted file mode 100644
index ab51923..0000000
--- a/src/Modules/Networks/NetworkCircuitSchema.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// src/Modues/Network/NetworkCircuit.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const networkCircuitSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .description('NetworkCircuit')
-  .prop('id', jsonSchema.string().description('Circuit Id').required())
-  .prop('speed', jsonSchema.string().description('Circuit Speed'));
diff --git a/src/Modules/Networks/NetworkController.ts b/src/Modules/Networks/NetworkController.ts
index c00fe04..983d97f 100644
--- a/src/Modules/Networks/NetworkController.ts
+++ b/src/Modules/Networks/NetworkController.ts
@@ -1,12 +1,22 @@
 // src/Modules/Networks/NetworkController.ts
+import { Address4 } from 'ip-address';
 import { Inject, Service } from 'typedi';
+import { Context, contextToken } from '../../Library/Context';
+import { createContainerName } from '../../Utils/Containers';
 import { Network } from './Network';
-import { Address4 } from 'ip-address';
 
 @Service()
 export class NetworkController {
-  @Inject('networks')
-  public networks: Network[];
+  @Inject(contextToken)
+  public context: Context;
+
+  public get networks(): Network[] {
+    const networkIds = this.context.container.getMany('network');
+
+    return networkIds.map((networkId) =>
+      this.context.container.get(createContainerName('NETWORK', networkId)),
+    );
+  }
 
   public findIP(ipAddress: Address4): Network[] {
     return this.networks.filter((network) =>
diff --git a/src/Modules/Networks/NetworkHost.ts b/src/Modules/Networks/NetworkHost.ts
index a511a3a..956d4be 100644
--- a/src/Modules/Networks/NetworkHost.ts
+++ b/src/Modules/Networks/NetworkHost.ts
@@ -1,32 +1,74 @@
 // src/Modules/Networks/NetworkHost.ts
-import Container, { Service } from 'typedi';
+import { Type } from 'class-transformer';
+import { IsOptional, IsString } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Service, Container } from 'typedi';
 import { createContainerName } from '../../Utils/Containers';
+import { IsValidID } from '../../Utils/Validator';
 import { Contact } from '../Contacts/Contact';
-import {
-  NetworkDeviceLink,
-  NetworkHost as IPAMNetworkHost,
-} from '../IPAM/IPAMConfig.gen';
-import { NetworkDevice } from '../NetworkDevices/NetworkDevice';
+import { SiteDevice } from '../SiteDevice/SiteDevice';
 import { Network } from './Network';
+import { NetworkHostDevice } from './NetworkHostDevice';
 
+@JSONSchema({
+  title: 'NetworkHost',
+  description: 'TODO',
+  additionalProperties: false,
+})
 @Service()
-export class NetworkHost implements IPAMNetworkHost {
+export class NetworkHost {
+  @IsString()
+  @JSONSchema({
+    description: 'IP Address for this host entry',
+  })
   public ip: string;
 
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    description: 'Friendly Description for the Network Host',
+  })
+  public description?: string;
+
   /**
-   * Friendly Description for the Network Host
+   * TODO: Create Network Device Link Schema
    */
-  public description: string;
 
-  public device?: NetworkDeviceLink;
+  @IsOptional()
+  @Type(() => NetworkHostDevice)
+  @JSONSchema({
+    deprecated: true,
+  })
+  public device?: NetworkHostDevice;
+
+  @IsOptional()
+  @IsValidID('SITEDEVICE')
+  @JSONSchema({
+    description: 'Site Device Reference ID',
+  })
+  public deviceId?: string;
 
+  @IsOptional()
+  @JSONSchema({
+    description: 'Site Device Interface',
+  })
+  public deviceInterface: string;
+
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    description: 'Friendly Description for the Network Host',
+  })
   public hostname?: string;
 
   public parentNetworkId: string;
 
-  /**
-   * Unique Contact Id reference
-   */
+  @IsOptional()
+  @IsString()
+  @IsValidID('CONTACT')
+  @JSONSchema({
+    description: 'Reference ID for Contact',
+  })
   public contactId?: string;
 
   /**
@@ -47,13 +89,9 @@ export class NetworkHost implements IPAMNetworkHost {
     return Container.get(createContainerName('NETWORK', this.parentNetworkId));
   }
 
-  public get coreDevice(): NetworkDevice | undefined {
+  public get coreDevice(): SiteDevice | undefined {
     if (this.device?.id) {
-      return Container.get(createContainerName('SITE_DEVICE', this.device.id));
+      return Container.get(createContainerName('SITEDEVICE', this.device.id));
     }
   }
-
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
 }
diff --git a/src/Modules/Networks/NetworkHostDevice.ts b/src/Modules/Networks/NetworkHostDevice.ts
new file mode 100644
index 0000000..bf15431
--- /dev/null
+++ b/src/Modules/Networks/NetworkHostDevice.ts
@@ -0,0 +1,27 @@
+// src/Modules/Networks/NetworkHostDevice.ts
+import { IsOptional, IsString } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Service } from 'typedi';
+import { IsValidID } from '../../Utils/Validator';
+
+@JSONSchema({
+  title: 'NetworkHostDevice',
+  description: 'Community Site Device connection for a Network Host',
+})
+@Service()
+export class NetworkHostDevice {
+  @IsString()
+  @IsValidID('SITEDEVICE')
+  @JSONSchema({
+    description: 'Reference ID for Site Device',
+  })
+  public id: string;
+
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    description:
+      'Interface on the Site Device with the Host IP address configured',
+  })
+  public interface?: string;
+}
diff --git a/src/Modules/Networks/NetworkHostSchema.ts b/src/Modules/Networks/NetworkHostSchema.ts
deleted file mode 100644
index ba694b6..0000000
--- a/src/Modules/Networks/NetworkHostSchema.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-// src/Modules/Network/NetworkHostSchema.ts
-import jsonSchema from 'fluent-json-schema';
-
-export const networkHostSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .description('Indivual Network host')
-  .prop(
-    'ip',
-    jsonSchema
-      .string()
-      .description('Host IP Address')
-      .format(jsonSchema.FORMATS.IPV4)
-      .required(),
-  )
-  .prop(
-    'hostname',
-    jsonSchema
-      .string()
-      .description('Hostname for reverse DNS creation')
-      .format(jsonSchema.FORMATS.HOSTNAME),
-  )
-  .prop('contactId', jsonSchema.ref('#/definitions/contactId'))
-  .prop('description', jsonSchema.string())
-  .prop('device', jsonSchema.ref('#/definitions/networkDeviceLink'));
diff --git a/src/Modules/Networks/NetworkRange.ts b/src/Modules/Networks/NetworkRange.ts
new file mode 100644
index 0000000..20a604c
--- /dev/null
+++ b/src/Modules/Networks/NetworkRange.ts
@@ -0,0 +1,39 @@
+// src/Modules/Networks/NetworkRange.ts
+import { IsIP, IsOptional, IsString } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { Service } from 'typedi';
+import { NetworkRangeType } from './NetworkRangeType';
+
+@JSONSchema({
+  title: 'NetworkRange',
+})
+@Service()
+export class NetworkRange {
+  @IsString()
+  @IsIP()
+  @JSONSchema({
+    description: 'Start IP of the range',
+  })
+  public start: string;
+
+  @IsString()
+  @IsIP()
+  @JSONSchema({
+    description: 'Start IP of the range',
+  })
+  public end: string;
+
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    description: 'Friendly description of the range',
+  })
+  public description?: string;
+
+  @IsString()
+  @JSONSchema({
+    description: 'Usage/type of this range',
+    enum: Object.values(NetworkRangeType),
+  })
+  public type: NetworkRangeType;
+}
diff --git a/src/Modules/Networks/NetworkRangeSchema.ts b/src/Modules/Networks/NetworkRangeSchema.ts
deleted file mode 100644
index 2fd5bb3..0000000
--- a/src/Modules/Networks/NetworkRangeSchema.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-// src/Modules/Network/NetworkRangeSchema.ts
-import jsonSchema from 'fluent-json-schema';
-import { NetworkRangeType } from './NetworkRangeType';
-
-export const networkRangeSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .description('Network Range')
-  .prop(
-    'start',
-    jsonSchema
-      .string()
-      .description('Start IP for the range')
-      .format(jsonSchema.FORMATS.IPV4)
-      .required(),
-  )
-  .prop(
-    'end',
-    jsonSchema
-      .string()
-      .description('End IP for the range')
-      .format(jsonSchema.FORMATS.IPV4)
-      .required(),
-  )
-  .prop('description', jsonSchema.string())
-  .prop('type', jsonSchema.string().enum(Object.values(NetworkRangeType)));
diff --git a/src/Modules/Networks/NetworkSchema.ts b/src/Modules/Networks/NetworkSchema.ts
deleted file mode 100644
index 4d8d7a7..0000000
--- a/src/Modules/Networks/NetworkSchema.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-// src/Modues/Network/NetworkSchema.ts
-import jsonSchema from 'fluent-json-schema';
-import { NetworkType } from './NetworkType';
-
-export const networkSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .description('Network')
-  .prop('prefix', jsonSchema.string().description('Network Prefix'))
-  .prop('description', jsonSchema.string())
-  .prop('circuit', jsonSchema.ref('#/definitions/networkcircuit'))
-  .prop(
-    'nsServers',
-    jsonSchema
-      .array()
-      .items(
-        jsonSchema
-          .string()
-          .description('Reverse DNS NS Server')
-          .format(jsonSchema.FORMATS.HOSTNAME),
-      ),
-  )
-  .prop(
-    'type',
-    jsonSchema
-      .string()
-      .description(`Network Type`)
-      .enum(Object.values(NetworkType)),
-  )
-  .prop('contactId', jsonSchema.ref('#/definitions/contactId'))
-  .prop(
-    'hosts',
-    jsonSchema.array().items(jsonSchema.ref('#/definitions/networkHost')),
-  )
-  .prop(
-    'ranges',
-    jsonSchema.array().items(jsonSchema.ref('#/definitions/networkRange')),
-  )
-  .prop(
-    'networks',
-    jsonSchema
-      .array()
-      .items(jsonSchema.ref('#/definitions/network'))
-      .uniqueItems(true)
-      .description('Children Networks'),
-  );
diff --git a/src/Modules/Networks/PrefixValidator.ts b/src/Modules/Networks/PrefixValidator.ts
new file mode 100644
index 0000000..9394754
--- /dev/null
+++ b/src/Modules/Networks/PrefixValidator.ts
@@ -0,0 +1,54 @@
+// src/Modules/Networks/PrefixValidator.ts
+import {
+  ValidationArguments,
+  ValidatorConstraint,
+  ValidatorConstraintInterface,
+} from 'class-validator';
+import { Address4 } from 'ip-address';
+import { Service, Container } from 'typedi';
+import { contextToken } from '../../Library/Context';
+import { createContainerName } from '../../Utils/Containers';
+import { Network } from './Network';
+
+@Service()
+@ValidatorConstraint({ name: 'ValidPrefix', async: false })
+export class ValidPrefix implements ValidatorConstraintInterface {
+  public validate(prefix: string): boolean {
+    return Address4.isValid(prefix);
+  }
+
+  public defaultMessage(): string {
+    // here you can provide default error message if validation failed
+    /**
+     * TODO: Setup IPv6 Support
+     */
+    return 'Prefix ($value) is not a valid IPv4 Prefix!';
+  }
+}
+
+@ValidatorConstraint({ name: 'ValidSubnet', async: false })
+export class ValidSubnet implements ValidatorConstraintInterface {
+  public validate(prefix: string, args: ValidationArguments): boolean {
+    try {
+      return (
+        (args.object as Network | undefined)?.IPv4.isInSubnet(
+          Container.get(contextToken).container.get(
+            createContainerName('NETWORK', prefix),
+          ).IPv4,
+        ) || false
+      );
+    } catch {
+      return false;
+    }
+  }
+
+  public defaultMessage(args: ValidationArguments): string {
+    args.property = 'prefix';
+
+    // here you can provide default error message if validation failed
+    /**
+     * TODO: Setup IPv6 Support
+     */
+    return 'Prefix ($value) is not a valid parent IPv4 Prefix of this network!';
+  }
+}
diff --git a/src/Modules/Networks/fixtures/Networks.yaml b/src/Modules/Networks/fixtures/Networks.yaml
new file mode 100644
index 0000000..dfee31f
--- /dev/null
+++ b/src/Modules/Networks/fixtures/Networks.yaml
@@ -0,0 +1,55 @@
+communities:
+  - name: Toronto
+    id: tor
+    contactId: tor.todo1
+    sites:
+      - id: tor.c1
+        name: Toronto Cabniet 12
+        devices:
+          - id: tor.c1.rt1
+            name: Torotno Cabinet 1 Router 1
+
+      - id: tor.c2
+        name: Toronto Cabniet 2
+        devices:
+          - id: tor.c2.rt1
+            name: Torotno Cabinet 2 Router 1
+
+circuits:
+  - id: tor.clink
+    sideAID: tor.c1
+    sideZID: tor.c2
+    speed: 10G
+
+circuitLocations:
+  - id: tor.c1
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+  - id: tor.c2
+    address: Front Street
+    provider: Bell
+    communuityId: tor
+    demarcSpeed: 10G
+
+contacts:
+  - id: tor.todo1
+    name: TODO
+
+networks:
+  - prefix: 1.0.0.0/23
+    networks:
+      - prefix: 1.0.0.0/30
+        description: Toronto Cabniet P2P
+        hosts:
+          - ip: 1.0.0.1
+            description: Toronto Cabniet 1
+            contactId: tor.todo1
+            deviceId: tor.c1.rt1
+            deviceInterface: TenGigE0/0/0/1
+          - ip: 1.0.0.2
+            description: Toronto Cabniet 2
+            deviceId: tor.c2.rt1
+            deviceInterface: TenGigE0/0/0/2
diff --git a/src/Modules/NetworkDevices/NetworkDeviceInterface.ts b/src/Modules/SiteDevice/NetworkDeviceInterface.ts
similarity index 100%
rename from src/Modules/NetworkDevices/NetworkDeviceInterface.ts
rename to src/Modules/SiteDevice/NetworkDeviceInterface.ts
diff --git a/src/Modules/NetworkDevices/NetworkDeviceInterfaceType.ts b/src/Modules/SiteDevice/NetworkDeviceInterfaceType.ts
similarity index 100%
rename from src/Modules/NetworkDevices/NetworkDeviceInterfaceType.ts
rename to src/Modules/SiteDevice/NetworkDeviceInterfaceType.ts
diff --git a/src/Modules/NetworkDevices/NetworkDeviceType.ts b/src/Modules/SiteDevice/NetworkDeviceType.ts
similarity index 100%
rename from src/Modules/NetworkDevices/NetworkDeviceType.ts
rename to src/Modules/SiteDevice/NetworkDeviceType.ts
diff --git a/src/Modules/NetworkDevices/NetworkDevice.ts b/src/Modules/SiteDevice/SiteDevice.ts
similarity index 62%
rename from src/Modules/NetworkDevices/NetworkDevice.ts
rename to src/Modules/SiteDevice/SiteDevice.ts
index dbadb4a..d0591cf 100644
--- a/src/Modules/NetworkDevices/NetworkDevice.ts
+++ b/src/Modules/SiteDevice/SiteDevice.ts
@@ -1,35 +1,54 @@
 // src/Modules/NetworkDevices/NetworkDevice.ts
-import Container, { Service } from 'typedi';
-import {
-  Device as IPAMDevice,
-  NetworkDeviceType,
-} from '../IPAM/IPAMConfig.gen';
+import { Service } from 'typedi';
 import { NetworkHost } from '../Networks/NetworkHost';
 import { NetworkDeviceInterface } from './NetworkDeviceInterface';
 import { Address4 } from 'ip-address';
+import { JSONSchema } from 'class-validator-jsonschema';
+import { NetworkDeviceType } from './NetworkDeviceType';
+import { IsOptional, IsString } from 'class-validator';
+import { getManyContainer } from '../../Utils/Containers';
 
+@JSONSchema({
+  title: 'SiteDevice',
+})
 @Service()
-export class NetworkDevice implements IPAMDevice {
-  /**
-   * Unique Device Id for usage in YAML references
-   */
+export class SiteDevice {
+  @IsString()
+  @JSONSchema({
+    description:
+      'Unique Network Device ID used for refences from other objects',
+  })
   public id: string;
 
-  /**
-   * Friendly name
-   */
+  @IsString()
+  @JSONSchema({
+    description: 'Friendly name for this device',
+  })
   public name: string;
 
   /**
    * Network Device Type
    */
+
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    enum: Object.values(NetworkDeviceType),
+    description:
+      'Type of the device, used for tracing, and for reverse dns creation',
+  })
   public type: NetworkDeviceType;
 
+  /**
+   * TODO: Clean this up
+   */
+
   private networkHosts: NetworkHost[];
 
   /**
    * All Network Device Interfaces for this device
    */
+
   public get interfaces(): NetworkDeviceInterface[] {
     const networkHosts = this.getNetworkHosts();
 
@@ -47,7 +66,7 @@ export class NetworkDevice implements IPAMDevice {
 
   public getNetworkHosts(): NetworkHost[] {
     if (!this.networkHosts) {
-      const networkHosts = Container.getMany('NETWORK_HOST');
+      const networkHosts = getManyContainer('NETWORKHOST');
 
       this.networkHosts = networkHosts.filter(
         (networkHost) => networkHost.device?.id === this.id,
@@ -60,13 +79,10 @@ export class NetworkDevice implements IPAMDevice {
   /**
    * Get all IP addresses for this device
    */
+
   public getAllIPs(): string[] {
     return this.getNetworkHosts()
       .map(({ device, ip }) => (device?.id === this.id ? ip : undefined))
       .filter(Boolean) as string[];
   }
-
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
 }
diff --git a/src/Modules/Sites/Site.ts b/src/Modules/Sites/Site.ts
index 7a5adda..83fd2de 100644
--- a/src/Modules/Sites/Site.ts
+++ b/src/Modules/Sites/Site.ts
@@ -1,17 +1,55 @@
 // src/Modules/Sites/Site.ts
-import { Service } from 'typedi';
-import { CommunitySite as IPAMCommunitySite } from '../IPAM/IPAMConfig.gen';
-import { NetworkDevice } from '../NetworkDevices/NetworkDevice';
+import { Transform, Type } from 'class-transformer';
+import { IsOptional, IsString, ValidateNested } from 'class-validator';
+import { JSONSchema } from 'class-validator-jsonschema';
+import Container, { Service } from 'typedi';
+import { contextToken } from '../../Library/Context';
+import { setContainer } from '../../Utils/Containers';
+import { SiteDevice } from '../SiteDevice/SiteDevice';
+import { SiteType } from './SiteType';
 
+@JSONSchema({
+  title: 'Site',
+  description: 'Site within a community which contains devices',
+  additionalProperties: false,
+  required: ['id', 'name'],
+})
 @Service()
-export class Site implements IPAMCommunitySite {
+export class Site {
+  @IsString()
+  @JSONSchema({
+    description:
+      'Unique Site ID used for refences from other objects, generally best practice to do COMMUNITYID.SITE_TYPE',
+  })
   public id: string;
 
+  @IsString()
+  @JSONSchema({
+    description: 'Friendly name of the community site',
+  })
   public name: string;
 
-  public devices: NetworkDevice[];
+  @IsOptional()
+  @IsString()
+  @JSONSchema({
+    description: 'Type of the site',
+    enum: Object.values(SiteType),
+  })
+  public type?: SiteType;
 
-  public constructor(options: Partial) {
-    Object.assign(this, options);
-  }
+  @ValidateNested({ each: true })
+  @Transform((items: SiteDevice[]) => {
+    items.map((item) =>
+      setContainer(
+        'SITEDEVICE',
+        item.id,
+        item,
+        Container.get(contextToken).container,
+      ),
+    );
+
+    return items;
+  }, {})
+  @Type(() => SiteDevice)
+  public devices: SiteDevice[];
 }
diff --git a/src/Modules/Sites/SiteSchema.ts b/src/Modules/Sites/SiteSchema.ts
deleted file mode 100644
index dc6c0fe..0000000
--- a/src/Modules/Sites/SiteSchema.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// src/Modules/Sites/SiteSchema.ts
-import jsonSchema from 'fluent-json-schema';
-import { SiteType } from './SiteType';
-
-export const siteSchema = jsonSchema
-  .object()
-  .additionalProperties(false)
-  .description('Community Site')
-  .prop('id', jsonSchema.string().description('Site short id').required())
-  .prop('name', jsonSchema.string().required())
-  .prop('type', jsonSchema.string().enum(Object.values(SiteType)))
-  .prop(
-    'devices',
-    jsonSchema.array().items(jsonSchema.ref('#/definitions/device')),
-  );
diff --git a/src/Utils/Containers.ts b/src/Utils/Containers.ts
index c63fb98..b59bb70 100644
--- a/src/Utils/Containers.ts
+++ b/src/Utils/Containers.ts
@@ -1,36 +1,7 @@
 // src/Utils/Containers.ts
 
 import Container from 'typedi';
-import { Circuit } from '../Modules/Circuits/Circuit';
-import { CircuitLocation } from '../Modules/Circuits/CircuitLocation';
-import { Community } from '../Modules/Communities/Community';
-import { Site } from '../Modules/Sites/Site';
-import { Contact } from '../Modules/Contacts/Contact';
-import { NetworkDevice } from '../Modules/NetworkDevices/NetworkDevice';
-import { Network } from '../Modules/Networks/Network';
-import { NetworkHost } from '../Modules/Networks/NetworkHost';
-
-enum ContainerKeys {
-  CONTACT = 'contact-',
-  COMMUNITY = 'community-',
-  SITE_DEVICE = 'networkDevice-',
-  SITE = 'communitySite-',
-  CIRCUIT_LOCATION = 'circuitLocation-',
-  CIRCUIT = 'circuit-',
-  NETWORK_HOST = 'networkHost-',
-  NETWORK = 'network-',
-}
-
-type ValueTypes = {
-  CONTACT: Contact;
-  COMMUNITY: Community;
-  SITE_DEVICE: NetworkDevice;
-  SITE: Site;
-  CIRCUIT_LOCATION: CircuitLocation;
-  CIRCUIT: Circuit;
-  NETWORK_HOST: NetworkHost;
-  NETWORK: Network;
-};
+import { ContainerKeys, ValueTypes } from './Types';
 
 export function createContainerName<
   T extends keyof typeof ContainerKeys,
@@ -43,17 +14,25 @@ export function setContainer(
   key: T,
   id: string,
   value: ValueTypes[T],
-  container = Container,
+  container = Container.of(),
 ): void {
   const containerName = createContainerName(key, id);
 
-  if (key === 'NETWORK_HOST') {
-    container.set({
-      id: key,
-      value,
-      multiple: true,
-    });
-  }
-
   container.set(containerName, value);
+  container.set({
+    id: key,
+    value: id,
+    multiple: true,
+  });
+}
+
+export function getManyContainer(
+  key: T,
+  container = Container.of(),
+): ValueTypes[T][] {
+  const valueIds = container.getMany(key);
+
+  return valueIds.map((valueId) =>
+    container.get(createContainerName(key, valueId)),
+  );
 }
diff --git a/src/Utils/Strings.test.ts b/src/Utils/Strings.test.ts
new file mode 100644
index 0000000..8c71b22
--- /dev/null
+++ b/src/Utils/Strings.test.ts
@@ -0,0 +1,23 @@
+// src/Utils/Strings.test.ts
+import { TestSuite } from '@k-foss/ts-estests';
+import { deepStrictEqual } from 'assert';
+
+export class StringUtilTestSuite extends TestSuite {
+  public testName = 'String Util Test Suite';
+
+  public async test(): Promise {
+    const { toTitleCase } = await import('./Strings');
+
+    deepStrictEqual(
+      toTitleCase('CONTACTS'),
+      'Contacts',
+      `toTitleCase('CONTACTS') === 'Contacts'`,
+    );
+
+    deepStrictEqual(
+      toTitleCase('HELLO WORLD'),
+      'Hello World',
+      `toTitleCase('HELLO WORLD') === 'Hello World'`,
+    );
+  }
+}
diff --git a/src/Utils/Strings.ts b/src/Utils/Strings.ts
new file mode 100644
index 0000000..bc39861
--- /dev/null
+++ b/src/Utils/Strings.ts
@@ -0,0 +1,21 @@
+// src/Utils/Strings.ts
+
+/**
+ * Convert a input string to title case
+ * @param input Input String `helloWorld`
+ *
+ * @returns Title case string
+ *
+ * @example
+ * ```ts
+ * const resultString = toTitleCase('contact')
+ * // resultString = 'Contact'
+ * ```
+ */
+export function toTitleCase(input: string): string {
+  return input
+    .toLowerCase()
+    .split(' ')
+    .map((word) => word.charAt(0).toUpperCase() + word.substring(1))
+    .join(' ');
+}
diff --git a/src/Utils/Types.ts b/src/Utils/Types.ts
new file mode 100644
index 0000000..bd38060
--- /dev/null
+++ b/src/Utils/Types.ts
@@ -0,0 +1,165 @@
+// src/Utils/Types.ts
+import { Circuit } from '../Modules/Circuits/Circuit';
+import { CircuitLocation } from '../Modules/Circuits/CircuitLocation';
+import { Community } from '../Modules/Communities/Community';
+import { Site } from '../Modules/Sites/Site';
+import { Contact } from '../Modules/Contacts/Contact';
+import { SiteDevice } from '../Modules/SiteDevice/SiteDevice';
+import { Network } from '../Modules/Networks/Network';
+import { NetworkHost } from '../Modules/Networks/NetworkHost';
+
+export type ValueTypes = {
+  CONTACT: Contact;
+  COMMUNITY: Community;
+  SITEDEVICE: SiteDevice;
+  SITE: Site;
+  CIRCUITLOCATION: CircuitLocation;
+  CIRCUIT: Circuit;
+  NETWORKHOST: NetworkHost;
+  NETWORK: Network;
+};
+
+export type ContainerKeyMap = {
+  [key in keyof ValueTypes]: ValueTypes[key] extends {
+    constructor: { name: string };
+  }
+    ? `${Lowercase}-`
+    : string;
+};
+
+export const ContainerKeys: ContainerKeyMap = {
+  CONTACT: 'contact-',
+  COMMUNITY: 'community-',
+  SITEDEVICE: 'sitedevice-',
+  SITE: 'site-',
+  CIRCUITLOCATION: 'circuitlocation-',
+  CIRCUIT: 'circuit-',
+  NETWORKHOST: 'networkhost-',
+  NETWORK: 'network-',
+} as const;
+
+// export enum ContainerKeys {}
+/* 
+type TypeIDField = {
+  [key in keyof typeof ContainerKeys]: keyof ValueTypes[key];
+}; */
+
+export const idFields = {
+  CIRCUIT: 'id',
+  CIRCUITLOCATION: 'id',
+  COMMUNITY: 'id',
+  CONTACT: 'id',
+  NETWORK: 'prefix',
+  NETWORKHOST: 'ip',
+  SITE: 'id',
+  SITEDEVICE: 'id',
+} as const;
+
+// export enum TypeIDField {
+//   CONTACT = 'id',
+//   COMMUNITY = 'id',
+//   SITEDEVICE = 'id',
+//   SITE = 'id',
+//   CIRCUITLOCATION = 'id',
+//   CIRCUIT = 'id',
+//   NETWORKHOST = 'ip',
+//   NETWORK = 'prefix',
+// }
+
+type IsIPAMType = T extends ValueTypes[keyof ValueTypes] ? true : false;
+
+/*
+type NonNullableUserPropertyKeys = {
+  [P in keyof User]: null extends User[P] ? never : P;
+}[keyof User];
+
+type NonNullablePropertyKeys = {
+  [P in keyof T]: null extends T[P] ? never : P;
+}[keyof T]; */
+
+// type IPAMType = IsIPAMType extends true ? true : false;
+
+type GetID = IsIPAMType extends true
+  ? {
+      [key in keyof ValueTypes]: ValueTypes[key] extends T
+        ? key extends keyof M
+          ? M[key]
+          : false
+        : false;
+    }[keyof ValueTypes]
+  : false;
+
+type IsContainerKey = T extends ContainerKeyMap[keyof ContainerKeyMap]
+  ? true
+  : false;
+
+// type GetIDField = IPAMType extends false ? never : TypeIDField;
+
+// type Testing2 = GetIDField;
+
+export function isContainerKey(key?: T): IsContainerKey {
+  if (typeof key === 'string') {
+    return Object.keys(ContainerKeys).includes(key ?? '') as IsContainerKey;
+  }
+
+  return false as IsContainerKey;
+}
+export interface ClassType {
+  new (...args: any[]): T;
+}
+
+// type ObjectClass = ClassType extends infer r ? r : unknown;
+
+export function isIPAMType(
+  type: ValueTypes[keyof ValueTypes],
+): type is ValueTypes[keyof ValueTypes] {
+  const className = type?.constructor.name.toUpperCase() as N;
+
+  if (isContainerKey(className) === true) {
+    return true;
+  }
+
+  return false;
+}
+
+export type ObjectGet = {
+  readonly [key in keyof X]: X[key] extends string | number
+    ? X[key]
+    : ObjectGet;
+};
+
+export type Unpacked = T extends (infer U)[]
+  ? U
+  : T extends (...args: any[]) => infer U
+  ? U
+  : T extends Promise
+  ? U
+  : T;
+
+export type ArrayType = T extends (infer A)[] ? A : T;
+
+export type Intersect = (T extends unknown ? (x: T) => 0 : never) extends (
+  x: infer R,
+) => 0
+  ? R
+  : never;
+
+export function getIDField<
+  T extends ValueTypes[keyof ValueTypes],
+  L extends GetID
+>(type: T): L extends string ? [L, string] : false {
+  const className = type?.constructor.name.toUpperCase() as keyof ValueTypes;
+
+  if (Object.keys(idFields).includes(className)) {
+    const field = idFields[className];
+
+    /**
+     * TODO: Make this type properly.
+     */
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore
+    return [field, type[field]] as L extends string ? [L, string] : false;
+  }
+
+  return false as L extends string ? [L, string] : false;
+}
diff --git a/src/Utils/Validator.ts b/src/Utils/Validator.ts
new file mode 100644
index 0000000..a219664
--- /dev/null
+++ b/src/Utils/Validator.ts
@@ -0,0 +1,38 @@
+/* eslint-disable @typescript-eslint/ban-types */
+// src/Utils/Validator.ts
+import { registerDecorator, ValidationOptions } from 'class-validator';
+import Container from 'typedi';
+import { contextToken } from '../Library/Context';
+import { createContainerName } from './Containers';
+import { toTitleCase } from './Strings';
+import { ContainerKeys } from './Types';
+
+export function IsValidID(
+  key: T,
+  validationOptions?: ValidationOptions,
+): (object: Object, propertyName: string) => void {
+  return function (object: Object, propertyName: string): void {
+    registerDecorator({
+      name: 'validId',
+      target: object.constructor,
+      propertyName: propertyName,
+      options: {
+        message: `${toTitleCase(key)} with ID ($value) does not exist!`,
+        ...validationOptions,
+      },
+      validator: {
+        validate(value: string): boolean {
+          try {
+            const linkedObject = Container.get(contextToken).container.get(
+              createContainerName(key, value),
+            );
+
+            return typeof linkedObject !== 'undefined';
+          } catch {
+            return false;
+          }
+        },
+      },
+    });
+  };
+}
diff --git a/src/Utils/ValidatorErrors.ts b/src/Utils/ValidatorErrors.ts
new file mode 100644
index 0000000..df5c63f
--- /dev/null
+++ b/src/Utils/ValidatorErrors.ts
@@ -0,0 +1,18 @@
+// src/Utils/ValidationErrors.ts
+import { ValidationError } from 'class-validator';
+
+/**
+ * Type Check an array testing if it's `class-validator` error objects
+ * @param errors Array of `class-validator` Error objects
+ *
+ * @returns True if array is validation objects, false if not
+ */
+export function isValidationErrors(
+  errors: ValidationError[] | ValidationError,
+): errors is ValidationError[] {
+  if (Array.isArray(errors)) {
+    return errors.every((validationError) => 'property' in validationError);
+  }
+
+  return 'property' in errors;
+}
diff --git a/src/bin/generateSchema.ts b/src/bin/generateSchema.ts
deleted file mode 100644
index fe0341d..0000000
--- a/src/bin/generateSchema.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/* eslint-disable @typescript-eslint/explicit-function-return-type */
-// src/bin/generateSchema.ts
-import { ObjectSchema } from 'fluent-json-schema';
-import { resolve } from 'path';
-import { fileURLToPath } from 'url';
-
-import { saveSchemaToDisk, saveSchemaTypesToDisk } from './Schema/Utils';
-
-const schemaJSONPath = resolve(
-  fileURLToPath(import.meta.url),
-  '../../../schemas',
-);
-
-const schemaName = process.argv[0];
-if (!schemaName) {
-  throw new Error('Schema name required.');
-}
-
-interface SchemaModule {
-  [key: string]: ObjectSchema;
-}
-
-type SchemaFile = {
-  importModule: () => Promise;
-  outputTypes?: string;
-  outputSchema?: boolean;
-  schemaName: string;
-};
-
-const schemas: SchemaFile[] = [
-  {
-    importModule: () => import('../Modules/IPAM/IPAMConfigSchema'),
-    outputTypes: '../Modules/IPAM/IPAMConfig.gen.ts',
-    outputSchema: true,
-    schemaName: 'IPAM',
-  },
-];
-
-const selectedSchema = schemas.find(
-  (schema) => schema.schemaName === schemaName,
-);
-if (!selectedSchema) {
-  throw new Error('Invalid schema name. Schema not found');
-}
-
-const importedModule = await selectedSchema.importModule();
-
-for (const [, exportedSchema] of Object.entries(importedModule)) {
-  const jsonSchema = exportedSchema.valueOf();
-  const schemaFilePath = resolve(schemaJSONPath, `${schemaName}.json`);
-
-  const promises = [];
-
-  if (selectedSchema.outputTypes) {
-    const typePath = resolve(
-      fileURLToPath(import.meta.url),
-      '../',
-      selectedSchema.outputTypes,
-    );
-
-    promises.push(saveSchemaTypesToDisk(jsonSchema, schemaName, typePath));
-  }
-
-  if (selectedSchema.outputSchema) {
-    promises.push(saveSchemaToDisk(jsonSchema, schemaFilePath));
-  }
-
-  await Promise.all(promises);
-}
diff --git a/src/bin/objectLab.ts b/src/bin/objectLab.ts
new file mode 100644
index 0000000..e0be219
--- /dev/null
+++ b/src/bin/objectLab.ts
@@ -0,0 +1,21 @@
+// src/bin/objectLab.ts
+const helloWorld = { test1: 'invalidTest1' };
+const helloWorld2 = { test2: 'invalidTest2' };
+
+enum CurrentObject {
+  HELLOWORLD,
+  HELLOWORLD2,
+}
+
+function getObject(currentObject: CurrentObject): { [key: string]: string } {
+  switch (currentObject) {
+    case CurrentObject.HELLOWORLD:
+      return helloWorld;
+    case CurrentObject.HELLOWORLD2:
+      return helloWorld2;
+  }
+}
+
+const currentValue = getObject(CurrentObject.HELLOWORLD2);
+
+console.log('Creating errors', Object.values(currentValue)[0]);
diff --git a/src/bin/runActions.ts b/src/bin/runActions.ts
new file mode 100644
index 0000000..0ced063
--- /dev/null
+++ b/src/bin/runActions.ts
@@ -0,0 +1,26 @@
+// src/bin/runActions.ts
+import 'reflect-metadata';
+import { logger, LogMode } from '../Library/Logger';
+import { useContainer } from 'class-validator';
+import { Container } from 'typedi';
+
+useContainer(Container, {
+  fallback: true,
+  fallbackOnErrors: true,
+});
+
+try {
+  const [{ IPAMController }] = await Promise.all([
+    import('../Modules/IPAM/IPAMController'),
+  ]);
+  const ipamController = IPAMController.createIPAM();
+
+  const config = await ipamController.loadIPAM('IPAM-Test.yaml');
+  logger.log(LogMode.INFO, `Config loaded`, config);
+} catch (errs) {
+  for (const err of errs) {
+    console.error(err);
+  }
+
+  process.exit(1);
+}
diff --git a/src/bin/saveSchema.ts b/src/bin/saveSchema.ts
new file mode 100644
index 0000000..e483b98
--- /dev/null
+++ b/src/bin/saveSchema.ts
@@ -0,0 +1,6 @@
+// src/bin/saveSchema.ts
+import { IPAMController } from '../Modules/IPAM/IPAMController';
+
+const ipamController = IPAMController.createIPAM();
+
+await ipamController.saveSchema();
diff --git a/src/index.ts b/src/index.ts
index 9af0fe6..c202c2e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,15 +2,37 @@
 import 'reflect-metadata';
 import { timeout } from './Utils/timeout';
 import { logger, LogMode } from './Library/Logger';
-import { ipamConfigController } from './Modules/IPAM/IPAMConfigController';
 import Container from 'typedi';
+import { IPAMController } from './Modules/IPAM/IPAMController';
+import { ValidationError } from 'class-validator';
+
+try {
+  const ipamController = Container.get(IPAMController);
+
+  const config = await ipamController.loadIPAM('IPAM-Test.yaml');
+
+  const toronto = config.communities.find(({ name }) => name === 'Toronto');
+
+  console.log(toronto);
+} catch (err) {
+  const test = err as ValidationError[];
+  console.log('Error', test);
+}
+
+// await ipamController.saveSchema();
+
+/*
+import { ipamConfigController } from './Modules/IPAM/IPAMConfigController';
+import Container, { Service } from 'typedi';
 import { NetworkController } from './Modules/Networks/NetworkController';
 import { Address4 } from 'ip-address';
 import { getSmallestSubnet } from './Utils/Networks';
+import { CircuitController } from './Modules/Circuits/CircuitController';
 
 const ipam = await ipamConfigController.loadFile('IPAM.yaml');
+Container.set('ipam', ipam);
 
-const communityCount = ipam.communities.length;
+/* const communityCount = ipam.communities.length;
 const totalCommunity = 80;
 
 console.log(
@@ -19,33 +41,13 @@ console.log(
   } remaining `,
 );
 
-const toronto = ipam.communities.find(({ id }) => id === 'tor');
-
-const c74 = toronto?.sites.find(({ id }) => id === 'tor.c74');
-
-const coreRouter = c74?.devices.find(({ id }) => id === 'tor.c74.rt1');
+Container.set('totalCommunities', 80);
+Container.set('rootSiteId', 'tor.c74');
+Container.set('rootDeviceId', 'tor.c74.rt1');
 
-const networkHosts = coreRouter?.getNetworkHosts();
+const circuitController = Container.get(CircuitController);
 
-if (networkHosts) {
-  for (const networkHost of networkHosts) {
-    const circuit = networkHost.parentNetwork.circuit;
-
-    if (networkHost.device?.interface && circuit?.id) {
-      console.log(
-        `${
-          networkHost.device.interface
-        } circuit run at ${circuit
-          .parsedCircuitSpeed()
-          .convertTo('Mb')} for community: ${
-          circuit.sideACircuitLocation.communuity.name
-        }`,
-      );
-    } else {
-      console.log(`No device Interface or circuit`, networkHost);
-    }
-  }
-}
+circuitController.listCircuits();
 
 const networkController = Container.get(NetworkController);
 
@@ -54,6 +56,12 @@ const networks = networkController.findIP(ddosIP);
 
 const device = getSmallestSubnet(networks);
 
+for (const service of Container.globalInstance.services as Service[]) {
+  console.log(service);
+}
+
+console.log(); */
+
 /* if (device.circuit?.speed) {
   for (const network of device.circuit.networks) {
     for (const host of network.hosts) {
@@ -168,6 +176,10 @@ async function sayHello(name = 'John'): Promise {
 
 logger.log(LogMode.INFO, `Starting TS-Core`);
 
+setInterval(() => {
+  console.log('Tester');
+}, 5000);
+
 await sayHello('K-FOSS');
 
 export {};
diff --git a/tsconfig.json b/tsconfig.json
index 4e84531..061df36 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -4,6 +4,7 @@
     "module": "ESNext",
     "moduleResolution": "Node",
     "allowSyntheticDefaultImports": true,
+    "lib": ["ESNext"],
 
     // Strict Rules
     "strict": true,
@@ -11,6 +12,10 @@
     "allowUnreachableCode": false,
     "allowUnusedLabels": false,
     "strictPropertyInitialization": false,
+    "noFallthroughCasesInSwitch": true,
+    "noImplicitAny": true,
+    "strictBindCallApply": true,
+    "useDefineForClassFields": true,
 
     // Source Maps
     "inlineSourceMap": true,