diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1a4c267503..dc27805e5f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -74,7 +74,7 @@ jobs:
   check-definitions:
      name: Check Definitions
      timeout-minutes: 5
-     runs-on: ubuntu-18.04
+     runs-on: ubuntu-latest
      steps:
       - uses: actions/checkout@v2
       - name: Use Node.js ${{ matrix.NODE_VERSION }}
diff --git a/.github/workflows/release-automated.yml b/.github/workflows/release-automated.yml
index 9c4a6c6896..271d4abca3 100644
--- a/.github/workflows/release-automated.yml
+++ b/.github/workflows/release-automated.yml
@@ -42,7 +42,7 @@ jobs:
     env:
       REGISTRY: docker.io
       IMAGE_NAME: parseplatform/parse-server
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-latest
     permissions:
       contents: read
       packages: write
@@ -86,7 +86,7 @@ jobs:
   docs:
     needs: release
     if: needs.release.outputs.current_tag != '' && github.ref == 'refs/heads/release'
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-latest
     timeout-minutes: 15
     steps:
       - uses: actions/checkout@v2
diff --git a/.github/workflows/release-manual-docker.yml b/.github/workflows/release-manual-docker.yml
index 3300f2a498..1d19189c3a 100644
--- a/.github/workflows/release-manual-docker.yml
+++ b/.github/workflows/release-manual-docker.yml
@@ -14,7 +14,7 @@ env:
   IMAGE_NAME: parseplatform/parse-server
 jobs:
   build:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-latest
     permissions:
       contents: read
       packages: write
diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md
index 18eb32b574..a2b4c268d6 100644
--- a/changelogs/CHANGELOG_alpha.md
+++ b/changelogs/CHANGELOG_alpha.md
@@ -1,3 +1,66 @@
+# [6.1.0-alpha.8](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.7...6.1.0-alpha.8) (2023-05-01)
+
+
+### Features
+
+* Allow multiple origins for header `Access-Control-Allow-Origin` ([#8517](https://github.com/parse-community/parse-server/issues/8517)) ([4f15539](https://github.com/parse-community/parse-server/commit/4f15539ac244aa2d393ac5177f7604b43f69e271))
+
+# [6.1.0-alpha.7](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.6...6.1.0-alpha.7) (2023-03-10)
+
+
+### Bug Fixes
+
+* Rate limiting across multiple servers via Redis not working ([#8469](https://github.com/parse-community/parse-server/issues/8469)) ([d9e347d](https://github.com/parse-community/parse-server/commit/d9e347d7413f30f58ffbb8397fc8b5ae23be6ff0))
+
+# [6.1.0-alpha.6](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.5...6.1.0-alpha.6) (2023-03-06)
+
+
+### Features
+
+* Add rate limiting across multiple servers via Redis ([#8394](https://github.com/parse-community/parse-server/issues/8394)) ([34833e4](https://github.com/parse-community/parse-server/commit/34833e42eec08b812b733be78df0535ab0e096b6))
+
+# [6.1.0-alpha.5](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.4...6.1.0-alpha.5) (2023-03-06)
+
+
+### Bug Fixes
+
+* LiveQuery can return incorrectly formatted date ([#8456](https://github.com/parse-community/parse-server/issues/8456)) ([4ce135a](https://github.com/parse-community/parse-server/commit/4ce135a4fe930776044bc8fd786a4e17a0144e03))
+
+# [6.1.0-alpha.4](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.3...6.1.0-alpha.4) (2023-03-06)
+
+
+### Bug Fixes
+
+* Parameters missing in `afterFind` trigger of authentication adapters ([#8458](https://github.com/parse-community/parse-server/issues/8458)) ([ce34747](https://github.com/parse-community/parse-server/commit/ce34747e8af54cb0b6b975da38f779a5955d2d59))
+
+# [6.1.0-alpha.3](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.2...6.1.0-alpha.3) (2023-03-06)
+
+
+### Features
+
+* Add `afterFind` trigger to authentication adapters ([#8444](https://github.com/parse-community/parse-server/issues/8444)) ([c793bb8](https://github.com/parse-community/parse-server/commit/c793bb88e7485743c7ceb65fe419cde75833ff33))
+
+# [6.1.0-alpha.2](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.1...6.1.0-alpha.2) (2023-03-05)
+
+
+### Bug Fixes
+
+* Nested date is incorrectly decoded as empty object `{}` when fetching a Parse Object ([#8446](https://github.com/parse-community/parse-server/issues/8446)) ([22d2446](https://github.com/parse-community/parse-server/commit/22d2446dfea2bc339affc20535d181097e152acf))
+
+# [6.1.0-alpha.1](https://github.com/parse-community/parse-server/compare/6.0.0...6.1.0-alpha.1) (2023-03-03)
+
+
+### Bug Fixes
+
+* Security upgrade jsonwebtoken to 9.0.0 ([#8420](https://github.com/parse-community/parse-server/issues/8420)) ([f5bfe45](https://github.com/parse-community/parse-server/commit/f5bfe4571e82b2b7440d41f3cff0d49937398164))
+
+### Features
+
+* Add option `schemaCacheTtl` for schema cache pulling as alternative to `enableSchemaHooks` ([#8436](https://github.com/parse-community/parse-server/issues/8436)) ([b3b76de](https://github.com/parse-community/parse-server/commit/b3b76de71b1d4265689d052e7837c38ec1fa4323))
+* Add Parse Server option `resetPasswordSuccessOnInvalidEmail` to choose success or error response on password reset with invalid email ([#7551](https://github.com/parse-community/parse-server/issues/7551)) ([e5d610e](https://github.com/parse-community/parse-server/commit/e5d610e5e487ddab86409409ac3d7362aba8f59b))
+* Deprecate LiveQuery `fields` option in favor of `keys` for semantic consistency ([#8388](https://github.com/parse-community/parse-server/issues/8388)) ([a49e323](https://github.com/parse-community/parse-server/commit/a49e323d5ae640bff1c6603ec37fdaddb9328dd1))
+* Export `AuthAdapter` to make it available for extension with custom authentication adapters ([#8443](https://github.com/parse-community/parse-server/issues/8443)) ([40c1961](https://github.com/parse-community/parse-server/commit/40c196153b8efa12ae384c1c0092b2ed60a260d6))
+
 # [6.0.0-alpha.35](https://github.com/parse-community/parse-server/compare/6.0.0-alpha.34...6.0.0-alpha.35) (2023-02-27)
 
 
diff --git a/jsdoc-conf.json b/jsdoc-conf.json
index ad059acda1..efbaa0a37c 100644
--- a/jsdoc-conf.json
+++ b/jsdoc-conf.json
@@ -1,10 +1,16 @@
 {
   "plugins": ["node_modules/jsdoc-babel", "plugins/markdown"],
   "babel": {
-      "plugins": ["@babel/plugin-transform-flow-strip-types"]
+    "plugins": ["@babel/plugin-transform-flow-strip-types"]
   },
   "source": {
-    "include":  ["./README.md", "./src/cloud-code", "./src/Options/docs.js", "./src/ParseServer.js", "./src/Adapters"],
+    "include": [
+      "README.md",
+      "./src/cloud-code",
+      "./src/Options/docs.js",
+      "./src/ParseServer.js",
+      "./src/Adapters"
+    ],
     "excludePattern": "(^|\\/|\\\\)_"
   },
   "templates": {
@@ -17,7 +23,18 @@
     "monospaceLinks": false
   },
   "opts": {
-    "template": "node_modules/@parse/minami",
-    "recurse": true
+    "encoding": "utf8",
+    "readme": "./README.md",
+    "recurse": true,
+    "template": "./node_modules/clean-jsdoc-theme",
+    "theme_opts": {
+      "default_theme": "dark",
+      "title": "
",
+      "create_style": "header, .sidebar-section-title, .sidebar-title { color: #139cee !important } .logo { margin-left : 40px; margin-right: 40px }"
+    }
+  },
+  "markdown": {
+    "hardwrap": false,
+    "idInHeadings": true
   }
-}
\ No newline at end of file
+}
diff --git a/package-lock.json b/package-lock.json
index fe5a6edfc0..ae752fdb36 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "parse-server",
-  "version": "6.1.0-beta.1",
+  "version": "6.1.0-alpha.8",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "parse-server",
-      "version": "6.1.0-beta.1",
+      "version": "6.1.0-alpha.8",
       "hasInstallScript": true,
       "license": "Apache-2.0",
       "dependencies": {
@@ -41,9 +41,10 @@
         "mustache": "4.2.0",
         "parse": "4.0.1",
         "path-to-regexp": "0.1.7",
-        "pg-monitor": "1.5.0",
-        "pg-promise": "10.12.1",
+        "pg-monitor": "2.0.0",
+        "pg-promise": "11.3.0",
         "pluralize": "8.0.0",
+        "rate-limit-redis": "3.0.1",
         "redis": "4.0.6",
         "semver": "7.3.8",
         "subscriptions-transport-ws": "0.11.0",
@@ -64,7 +65,6 @@
         "@babel/plugin-proposal-object-rest-spread": "7.10.0",
         "@babel/plugin-transform-flow-strip-types": "7.9.0",
         "@babel/preset-env": "7.10.0",
-        "@parse/minami": "1.0.0",
         "@saithodev/semantic-release-backmerge": "2.1.2",
         "@semantic-release/changelog": "5.0.1",
         "@semantic-release/commit-analyzer": "8.0.1",
@@ -75,6 +75,7 @@
         "all-node-versions": "11.3.0",
         "apollo-upload-client": "17.0.0",
         "bcrypt-nodejs": "0.0.3",
+        "clean-jsdoc-theme": "^4.2.7",
         "cross-env": "7.0.2",
         "deep-diff": "1.0.2",
         "eslint": "8.26.0",
@@ -594,9 +595,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.20.5",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
-      "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==",
+      "version": "7.21.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
+      "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==",
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -2287,6 +2288,18 @@
         "@jridgewell/sourcemap-codec": "1.4.14"
       }
     },
+    "node_modules/@jsdoc/salty": {
+      "version": "0.2.5",
+      "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz",
+      "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==",
+      "dev": true,
+      "dependencies": {
+        "lodash": "^4.17.21"
+      },
+      "engines": {
+        "node": ">=v12.0.0"
+      }
+    },
     "node_modules/@napi-rs/triples": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.1.0.tgz",
@@ -2745,12 +2758,6 @@
       "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.2.tgz",
       "integrity": "sha512-VUsVZXgt53FULqUd9xqGDW6RXes62qHXTNOeRSlS1MOemiCdtQOUGgLHgjdYQXnZ1hPLkxZKph96AluZUb953g=="
     },
-    "node_modules/@parse/minami": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@parse/minami/-/minami-1.0.0.tgz",
-      "integrity": "sha512-Rw+p0WdOOypFPVJsmhyiI+Q056ZxdP2iAtObnU1DZrsvKZTf5x0B/0SjIt0hUgWp+COjqi/p17VdBU9IAD/NJg==",
-      "dev": true
-    },
     "node_modules/@parse/node-apn": {
       "version": "5.1.3",
       "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.3.tgz",
@@ -4060,11 +4067,11 @@
       }
     },
     "node_modules/assert-options": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.7.0.tgz",
-      "integrity": "sha512-7q9uNH/Dh8gFgpIIb9ja8PJEWA5AQy3xnBC8jtKs8K/gNVCr1K6kIvlm59HUyYgvM7oEDoLzGgPcGd9FqhtXEQ==",
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.0.tgz",
+      "integrity": "sha512-qSELrEaEz4sGwTs4Qh+swQkjiHAysC4rot21+jzXU86dJzNG+FDqBzyS3ohSoTRf4ZLA3FSwxQdiuNl5NXUtvA==",
       "engines": {
-        "node": ">=8.0.0"
+        "node": ">=10.0.0"
       }
     },
     "node_modules/assert-plus": {
@@ -4686,6 +4693,16 @@
         "node": ">=6"
       }
     },
+    "node_modules/camel-case": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+      "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==",
+      "dev": true,
+      "dependencies": {
+        "no-case": "^2.2.0",
+        "upper-case": "^1.1.1"
+      }
+    },
     "node_modules/camelcase": {
       "version": "5.3.1",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -4858,6 +4875,59 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/clean-css": {
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
+      "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
+      "dev": true,
+      "dependencies": {
+        "source-map": "~0.6.0"
+      },
+      "engines": {
+        "node": ">= 4.0"
+      }
+    },
+    "node_modules/clean-css/node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/clean-jsdoc-theme": {
+      "version": "4.2.7",
+      "resolved": "https://registry.npmjs.org/clean-jsdoc-theme/-/clean-jsdoc-theme-4.2.7.tgz",
+      "integrity": "sha512-yLLxwTFw7N9/toUCcFmKkwJmv4LO2pQWYNETcU3Vv+n2al2L2ohb7xWoXLjp5m3OljC9b1m+o4adzY0YH6Ep4A==",
+      "dev": true,
+      "dependencies": {
+        "@jsdoc/salty": "^0.2.4",
+        "fs-extra": "^10.1.0",
+        "html-minifier": "^4.0.0",
+        "klaw-sync": "^6.0.0",
+        "lodash": "^4.17.21",
+        "nanoid": "^3.3.4",
+        "showdown": "^2.1.0"
+      },
+      "peerDependencies": {
+        "jsdoc": ">=3.x <=4.x"
+      }
+    },
+    "node_modules/clean-jsdoc-theme/node_modules/fs-extra": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/clean-stack": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -8718,6 +8788,15 @@
         "node": ">=8"
       }
     },
+    "node_modules/he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true,
+      "bin": {
+        "he": "bin/he"
+      }
+    },
     "node_modules/hoist-non-react-statics": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@@ -8766,6 +8845,33 @@
       "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
       "dev": true
     },
+    "node_modules/html-minifier": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
+      "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
+      "dev": true,
+      "dependencies": {
+        "camel-case": "^3.0.0",
+        "clean-css": "^4.2.1",
+        "commander": "^2.19.0",
+        "he": "^1.2.0",
+        "param-case": "^2.1.1",
+        "relateurl": "^0.2.7",
+        "uglify-js": "^3.5.1"
+      },
+      "bin": {
+        "html-minifier": "cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/html-minifier/node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true
+    },
     "node_modules/htmlparser2": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
@@ -10120,6 +10226,15 @@
         "graceful-fs": "^4.1.9"
       }
     },
+    "node_modules/klaw-sync": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+      "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.11"
+      }
+    },
     "node_modules/kuler": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
@@ -10885,6 +11000,12 @@
         "loose-envify": "cli.js"
       }
     },
+    "node_modules/lower-case": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+      "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
+      "dev": true
+    },
     "node_modules/lowercase-keys": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
@@ -12227,6 +12348,15 @@
       "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
       "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
     },
+    "node_modules/no-case": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+      "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+      "dev": true,
+      "dependencies": {
+        "lower-case": "^1.1.1"
+      }
+    },
     "node_modules/node-abort-controller": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz",
@@ -15901,6 +16031,15 @@
         "node": ">= 4.0.0"
       }
     },
+    "node_modules/param-case": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
+      "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==",
+      "dev": true,
+      "dependencies": {
+        "no-case": "^2.2.0"
+      }
+    },
     "node_modules/parent-module": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -16069,15 +16208,15 @@
       "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
     },
     "node_modules/pg": {
-      "version": "8.8.0",
-      "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz",
-      "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==",
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/pg/-/pg-8.9.0.tgz",
+      "integrity": "sha512-ZJM+qkEbtOHRuXjmvBtOgNOXOtLSbxiMiUVMgE4rV6Zwocy03RicCVvDXgx8l4Biwo8/qORUnEqn2fdQzV7KCg==",
       "dependencies": {
         "buffer-writer": "2.0.0",
         "packet-reader": "1.0.0",
         "pg-connection-string": "^2.5.0",
         "pg-pool": "^3.5.2",
-        "pg-protocol": "^1.5.0",
+        "pg-protocol": "^1.6.0",
         "pg-types": "^2.1.0",
         "pgpass": "1.x"
       },
@@ -16115,14 +16254,14 @@
       }
     },
     "node_modules/pg-monitor": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-1.5.0.tgz",
-      "integrity": "sha512-Zg5RpoYaz0zyRwAQWKrRxUZgzZ+/r4McMP4vEvg+qE8765SHAB1wHZL58uAjocG4WSK/NLP/zZhUuoyurw4l6Q==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-2.0.0.tgz",
+      "integrity": "sha512-UqjhroM701sRrJHhXeF1OwNBGxkN9R0YgkVU8A46wWn3RwK/K7QDylChMoDxo8TmGp86CBP4ZSf+RK9vD8XyVA==",
       "dependencies": {
         "cli-color": "2.0.3"
       },
       "engines": {
-        "node": ">=7.6"
+        "node": ">=14"
       }
     },
     "node_modules/pg-monitor/node_modules/cli-color": {
@@ -16189,23 +16328,23 @@
       }
     },
     "node_modules/pg-promise": {
-      "version": "10.12.1",
-      "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.12.1.tgz",
-      "integrity": "sha512-SiJkBUDGq7PNfJFJbWferodsSH+vLrhte0Q0kVgQbwlNYeKmp9Hhkr+357+5DWEuBGOHhSu1UQffSSf5HVqRtA==",
+      "version": "11.3.0",
+      "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.3.0.tgz",
+      "integrity": "sha512-A2CYmax5gsqVAO2N0ET9oPRCPX3kpKymj9qLVK7+jszlJL6l8uJDq/DGqLpxNi5VHwK7Dmm2WNRdrwkh1xuaxQ==",
       "dependencies": {
-        "assert-options": "0.7.0",
-        "pg": "8.8.0",
+        "assert-options": "0.8.0",
+        "pg": "8.9.0",
         "pg-minify": "1.6.2",
         "spex": "3.2.0"
       },
       "engines": {
-        "node": ">=12.0"
+        "node": ">=14.0"
       }
     },
     "node_modules/pg-protocol": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz",
-      "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ=="
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
+      "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
     },
     "node_modules/pg-types": {
       "version": "2.2.0",
@@ -16746,6 +16885,17 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/rate-limit-redis": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/rate-limit-redis/-/rate-limit-redis-3.0.1.tgz",
+      "integrity": "sha512-L6yhOUBrAZ8VEMX9DwlM3X6hfm8yq+gBO4LoOW7+JgmNq59zE7QmLz4v5VnwYPvLeSh/e7PDcrzUI3UumJw1iw==",
+      "engines": {
+        "node": ">= 14.5.0"
+      },
+      "peerDependencies": {
+        "express-rate-limit": "^6"
+      }
+    },
     "node_modules/raw-body": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
@@ -17308,6 +17458,15 @@
         "jsesc": "bin/jsesc"
       }
     },
+    "node_modules/relateurl": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+      "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
     "node_modules/release-zalgo": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
@@ -18151,6 +18310,31 @@
         "node": ">=8"
       }
     },
+    "node_modules/showdown": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz",
+      "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==",
+      "dev": true,
+      "dependencies": {
+        "commander": "^9.0.0"
+      },
+      "bin": {
+        "showdown": "bin/showdown.js"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://www.paypal.me/tiviesantos"
+      }
+    },
+    "node_modules/showdown/node_modules/commander": {
+      "version": "9.5.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+      "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+      "dev": true,
+      "engines": {
+        "node": "^12.20.0 || >=14"
+      }
+    },
     "node_modules/side-channel": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -19610,7 +19794,6 @@
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
       "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
       "dev": true,
-      "optional": true,
       "bin": {
         "uglifyjs": "bin/uglifyjs"
       },
@@ -19836,6 +20019,12 @@
         "browserslist": ">= 4.21.0"
       }
     },
+    "node_modules/upper-case": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+      "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
+      "dev": true
+    },
     "node_modules/uri-js": {
       "version": "4.4.1",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -20810,9 +20999,9 @@
       }
     },
     "@babel/parser": {
-      "version": "7.20.5",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
-      "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA=="
+      "version": "7.21.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
+      "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw=="
     },
     "@babel/plugin-proposal-object-rest-spread": {
       "version": "7.10.0",
@@ -22021,6 +22210,15 @@
         "@jridgewell/sourcemap-codec": "1.4.14"
       }
     },
+    "@jsdoc/salty": {
+      "version": "0.2.5",
+      "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz",
+      "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.21"
+      }
+    },
     "@napi-rs/triples": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.1.0.tgz",
@@ -22347,12 +22545,6 @@
       "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.2.tgz",
       "integrity": "sha512-VUsVZXgt53FULqUd9xqGDW6RXes62qHXTNOeRSlS1MOemiCdtQOUGgLHgjdYQXnZ1hPLkxZKph96AluZUb953g=="
     },
-    "@parse/minami": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@parse/minami/-/minami-1.0.0.tgz",
-      "integrity": "sha512-Rw+p0WdOOypFPVJsmhyiI+Q056ZxdP2iAtObnU1DZrsvKZTf5x0B/0SjIt0hUgWp+COjqi/p17VdBU9IAD/NJg==",
-      "dev": true
-    },
     "@parse/node-apn": {
       "version": "5.1.3",
       "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.3.tgz",
@@ -23386,9 +23578,9 @@
       }
     },
     "assert-options": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.7.0.tgz",
-      "integrity": "sha512-7q9uNH/Dh8gFgpIIb9ja8PJEWA5AQy3xnBC8jtKs8K/gNVCr1K6kIvlm59HUyYgvM7oEDoLzGgPcGd9FqhtXEQ=="
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.0.tgz",
+      "integrity": "sha512-qSELrEaEz4sGwTs4Qh+swQkjiHAysC4rot21+jzXU86dJzNG+FDqBzyS3ohSoTRf4ZLA3FSwxQdiuNl5NXUtvA=="
     },
     "assert-plus": {
       "version": "1.0.0",
@@ -23865,6 +24057,16 @@
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
       "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
     },
+    "camel-case": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+      "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==",
+      "dev": true,
+      "requires": {
+        "no-case": "^2.2.0",
+        "upper-case": "^1.1.1"
+      }
+    },
     "camelcase": {
       "version": "5.3.1",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -23997,6 +24199,51 @@
         "static-extend": "^0.1.1"
       }
     },
+    "clean-css": {
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
+      "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
+      "dev": true,
+      "requires": {
+        "source-map": "~0.6.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+          "dev": true
+        }
+      }
+    },
+    "clean-jsdoc-theme": {
+      "version": "4.2.7",
+      "resolved": "https://registry.npmjs.org/clean-jsdoc-theme/-/clean-jsdoc-theme-4.2.7.tgz",
+      "integrity": "sha512-yLLxwTFw7N9/toUCcFmKkwJmv4LO2pQWYNETcU3Vv+n2al2L2ohb7xWoXLjp5m3OljC9b1m+o4adzY0YH6Ep4A==",
+      "dev": true,
+      "requires": {
+        "@jsdoc/salty": "^0.2.4",
+        "fs-extra": "^10.1.0",
+        "html-minifier": "^4.0.0",
+        "klaw-sync": "^6.0.0",
+        "lodash": "^4.17.21",
+        "nanoid": "^3.3.4",
+        "showdown": "^2.1.0"
+      },
+      "dependencies": {
+        "fs-extra": {
+          "version": "10.1.0",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+          "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.2.0",
+            "jsonfile": "^6.0.1",
+            "universalify": "^2.0.0"
+          }
+        }
+      }
+    },
     "clean-stack": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -26989,6 +27236,12 @@
         }
       }
     },
+    "he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true
+    },
     "hoist-non-react-statics": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@@ -27030,6 +27283,29 @@
       "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
       "dev": true
     },
+    "html-minifier": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
+      "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
+      "dev": true,
+      "requires": {
+        "camel-case": "^3.0.0",
+        "clean-css": "^4.2.1",
+        "commander": "^2.19.0",
+        "he": "^1.2.0",
+        "param-case": "^2.1.1",
+        "relateurl": "^0.2.7",
+        "uglify-js": "^3.5.1"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+          "dev": true
+        }
+      }
+    },
     "htmlparser2": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
@@ -28074,6 +28350,15 @@
         "graceful-fs": "^4.1.9"
       }
     },
+    "klaw-sync": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+      "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.11"
+      }
+    },
     "kuler": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
@@ -28693,6 +28978,12 @@
         "js-tokens": "^3.0.0 || ^4.0.0"
       }
     },
+    "lower-case": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+      "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
+      "dev": true
+    },
     "lowercase-keys": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
@@ -29755,6 +30046,15 @@
       "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
       "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
     },
+    "no-case": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+      "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+      "dev": true,
+      "requires": {
+        "lower-case": "^1.1.1"
+      }
+    },
     "node-abort-controller": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz",
@@ -32407,6 +32707,15 @@
         "wcwidth": "^1.0.1"
       }
     },
+    "param-case": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
+      "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==",
+      "dev": true,
+      "requires": {
+        "no-case": "^2.2.0"
+      }
+    },
     "parent-module": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -32524,15 +32833,15 @@
       "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
     },
     "pg": {
-      "version": "8.8.0",
-      "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz",
-      "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==",
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/pg/-/pg-8.9.0.tgz",
+      "integrity": "sha512-ZJM+qkEbtOHRuXjmvBtOgNOXOtLSbxiMiUVMgE4rV6Zwocy03RicCVvDXgx8l4Biwo8/qORUnEqn2fdQzV7KCg==",
       "requires": {
         "buffer-writer": "2.0.0",
         "packet-reader": "1.0.0",
         "pg-connection-string": "^2.5.0",
         "pg-pool": "^3.5.2",
-        "pg-protocol": "^1.5.0",
+        "pg-protocol": "^1.6.0",
         "pg-types": "^2.1.0",
         "pgpass": "1.x"
       }
@@ -32553,9 +32862,9 @@
       "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg=="
     },
     "pg-monitor": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-1.5.0.tgz",
-      "integrity": "sha512-Zg5RpoYaz0zyRwAQWKrRxUZgzZ+/r4McMP4vEvg+qE8765SHAB1wHZL58uAjocG4WSK/NLP/zZhUuoyurw4l6Q==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-2.0.0.tgz",
+      "integrity": "sha512-UqjhroM701sRrJHhXeF1OwNBGxkN9R0YgkVU8A46wWn3RwK/K7QDylChMoDxo8TmGp86CBP4ZSf+RK9vD8XyVA==",
       "requires": {
         "cli-color": "2.0.3"
       },
@@ -32621,20 +32930,20 @@
       "requires": {}
     },
     "pg-promise": {
-      "version": "10.12.1",
-      "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.12.1.tgz",
-      "integrity": "sha512-SiJkBUDGq7PNfJFJbWferodsSH+vLrhte0Q0kVgQbwlNYeKmp9Hhkr+357+5DWEuBGOHhSu1UQffSSf5HVqRtA==",
+      "version": "11.3.0",
+      "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.3.0.tgz",
+      "integrity": "sha512-A2CYmax5gsqVAO2N0ET9oPRCPX3kpKymj9qLVK7+jszlJL6l8uJDq/DGqLpxNi5VHwK7Dmm2WNRdrwkh1xuaxQ==",
       "requires": {
-        "assert-options": "0.7.0",
-        "pg": "8.8.0",
+        "assert-options": "0.8.0",
+        "pg": "8.9.0",
         "pg-minify": "1.6.2",
         "spex": "3.2.0"
       }
     },
     "pg-protocol": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz",
-      "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ=="
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
+      "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
     },
     "pg-types": {
       "version": "2.2.0",
@@ -33032,6 +33341,12 @@
       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
     },
+    "rate-limit-redis": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/rate-limit-redis/-/rate-limit-redis-3.0.1.tgz",
+      "integrity": "sha512-L6yhOUBrAZ8VEMX9DwlM3X6hfm8yq+gBO4LoOW7+JgmNq59zE7QmLz4v5VnwYPvLeSh/e7PDcrzUI3UumJw1iw==",
+      "requires": {}
+    },
     "raw-body": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
@@ -33491,6 +33806,12 @@
         }
       }
     },
+    "relateurl": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+      "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
+      "dev": true
+    },
     "release-zalgo": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
@@ -34130,6 +34451,23 @@
       "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
       "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
     },
+    "showdown": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz",
+      "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==",
+      "dev": true,
+      "requires": {
+        "commander": "^9.0.0"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "9.5.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+          "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+          "dev": true
+        }
+      }
+    },
     "side-channel": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -35288,8 +35626,7 @@
       "version": "3.17.4",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
       "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "unbzip2-stream": {
       "version": "1.4.3",
@@ -35451,6 +35788,12 @@
         "picocolors": "^1.0.0"
       }
     },
+    "upper-case": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+      "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
+      "dev": true
+    },
     "uri-js": {
       "version": "4.4.1",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
diff --git a/package.json b/package.json
index 5cf9788023..cca14c5643 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "parse-server",
-  "version": "6.1.0-beta.1",
+  "version": "6.1.0-alpha.8",
   "description": "An express module providing a Parse-compatible API server",
   "main": "lib/index.js",
   "repository": {
@@ -50,9 +50,10 @@
     "mustache": "4.2.0",
     "parse": "4.0.1",
     "path-to-regexp": "0.1.7",
-    "pg-monitor": "1.5.0",
-    "pg-promise": "10.12.1",
+    "pg-monitor": "2.0.0",
+    "pg-promise": "11.3.0",
     "pluralize": "8.0.0",
+    "rate-limit-redis": "3.0.1",
     "redis": "4.0.6",
     "semver": "7.3.8",
     "subscriptions-transport-ws": "0.11.0",
@@ -70,7 +71,6 @@
     "@babel/plugin-proposal-object-rest-spread": "7.10.0",
     "@babel/plugin-transform-flow-strip-types": "7.9.0",
     "@babel/preset-env": "7.10.0",
-    "@parse/minami": "1.0.0",
     "@saithodev/semantic-release-backmerge": "2.1.2",
     "@semantic-release/changelog": "5.0.1",
     "@semantic-release/commit-analyzer": "8.0.1",
@@ -81,6 +81,7 @@
     "all-node-versions": "11.3.0",
     "apollo-upload-client": "17.0.0",
     "bcrypt-nodejs": "0.0.3",
+    "clean-jsdoc-theme": "4.2.7",
     "cross-env": "7.0.2",
     "deep-diff": "1.0.2",
     "eslint": "8.26.0",
diff --git a/resources/buildConfigDefinitions.js b/resources/buildConfigDefinitions.js
index 3a69217016..e0d33daa4b 100644
--- a/resources/buildConfigDefinitions.js
+++ b/resources/buildConfigDefinitions.js
@@ -161,6 +161,9 @@ function mapperFor(elt, t) {
     if (type == 'NumberOrBoolean') {
       return wrap(t.identifier('numberOrBooleanParser'));
     }
+    if (type === 'StringOrStringArray') {
+      return wrap(t.identifier('arrayParser'));
+    }
     return wrap(t.identifier('objectParser'));
   }
 }
@@ -278,6 +281,9 @@ function inject(t, list) {
         const adapterType = elt.typeAnnotation.typeParameters.params[0].id.name;
         type = `Adapter<${adapterType}>`;
       }
+      if (type === 'StringOrStringArray') {
+        type = 'String|String[]';
+      }
       comments += ` * @property {${type}} ${elt.name} ${elt.help}\n`;
       const obj = t.objectExpression(props);
       return t.objectProperty(t.stringLiteral(elt.name), obj);
diff --git a/spec/AuthenticationAdaptersV2.spec.js b/spec/AuthenticationAdaptersV2.spec.js
index 244349a89f..aaa172ea66 100644
--- a/spec/AuthenticationAdaptersV2.spec.js
+++ b/spec/AuthenticationAdaptersV2.spec.js
@@ -59,6 +59,19 @@ describe('Auth Adapter features', () => {
     validateLogin: () => Promise.resolve(),
   };
 
+  const modernAdapter3 = {
+    validateAppId: () => Promise.resolve(),
+    validateSetUp: () => Promise.resolve(),
+    validateUpdate: () => Promise.resolve(),
+    validateLogin: () => Promise.resolve(),
+    validateOptions: () => Promise.resolve(),
+    afterFind() {
+      return {
+        foo: 'bar',
+      };
+    },
+  };
+
   const wrongAdapter = {
     validateAppId: () => Promise.resolve(),
   };
@@ -332,6 +345,30 @@ describe('Auth Adapter features', () => {
     expect(user.getSessionToken()).toBeDefined();
   });
 
+  it('should strip out authData if required', async () => {
+    const spy = spyOn(modernAdapter3, 'validateOptions').and.callThrough();
+    const afterSpy = spyOn(modernAdapter3, 'afterFind').and.callThrough();
+    await reconfigureServer({ auth: { modernAdapter3 } });
+    const user = new Parse.User();
+    await user.save({ authData: { modernAdapter3: { id: 'modernAdapter3Data' } } });
+    await user.fetch({ sessionToken: user.getSessionToken() });
+    const authData = user.get('authData').modernAdapter3;
+    expect(authData).toEqual({ foo: 'bar' });
+    for (const call of afterSpy.calls.all()) {
+      const args = call.args[0];
+      if (args.user) {
+        user._objCount = args.user._objCount;
+        break;
+      }
+    }
+    expect(afterSpy).toHaveBeenCalledWith(
+      { ip: '127.0.0.1', user, master: false },
+      { id: 'modernAdapter3Data' },
+      undefined
+    );
+    expect(spy).toHaveBeenCalled();
+  });
+
   it('should throw if no triggers found', async () => {
     await reconfigureServer({ auth: { wrongAdapter } });
     const user = new Parse.User();
diff --git a/spec/Idempotency.spec.js b/spec/Idempotency.spec.js
index a45d19343c..813923b1ff 100644
--- a/spec/Idempotency.spec.js
+++ b/spec/Idempotency.spec.js
@@ -45,10 +45,6 @@ describe('Idempotency', () => {
     });
   });
 
-  afterAll(() => {
-    jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 10000;
-  });
-
   // Tests
   it('should enforce idempotency for cloud code function', async () => {
     let counter = 0;
diff --git a/spec/Middlewares.spec.js b/spec/Middlewares.spec.js
index 12bfc59bf7..636e7809f9 100644
--- a/spec/Middlewares.spec.js
+++ b/spec/Middlewares.spec.js
@@ -287,6 +287,35 @@ describe('middlewares', () => {
     expect(headers['Access-Control-Allow-Origin']).toEqual('https://parseplatform.org/');
   });
 
+  it('should support multiple origins if several are defined in allowOrigin as an array', () => {
+    AppCache.put(fakeReq.body._ApplicationId, {
+      allowOrigin: ['https://a.com', 'https://b.com', 'https://c.com'],
+    });
+    const headers = {};
+    const res = {
+      header: (key, value) => {
+        headers[key] = value;
+      },
+    };
+    const allowCrossDomain = middlewares.allowCrossDomain(fakeReq.body._ApplicationId);
+    // Test with the first domain
+    fakeReq.headers.origin = 'https://a.com';
+    allowCrossDomain(fakeReq, res, () => {});
+    expect(headers['Access-Control-Allow-Origin']).toEqual('https://a.com');
+    // Test with the second domain
+    fakeReq.headers.origin = 'https://b.com';
+    allowCrossDomain(fakeReq, res, () => {});
+    expect(headers['Access-Control-Allow-Origin']).toEqual('https://b.com');
+    // Test with the third domain
+    fakeReq.headers.origin = 'https://c.com';
+    allowCrossDomain(fakeReq, res, () => {});
+    expect(headers['Access-Control-Allow-Origin']).toEqual('https://c.com');
+    // Test with an unauthorized domain
+    fakeReq.headers.origin = 'https://unauthorized.com';
+    allowCrossDomain(fakeReq, res, () => {});
+    expect(headers['Access-Control-Allow-Origin']).toEqual('https://a.com');
+  });
+
   it('should use user provided on field userFromJWT', done => {
     AppCache.put(fakeReq.body._ApplicationId, {
       masterKey: 'masterKey',
diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js
index 58731d2432..1b5cc0c5e9 100644
--- a/spec/MongoStorageAdapter.spec.js
+++ b/spec/MongoStorageAdapter.spec.js
@@ -248,6 +248,10 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
     expect(object.date[0] instanceof Date).toBeTrue();
     expect(object.bar.date[0] instanceof Date).toBeTrue();
     expect(object.foo.test.date[0] instanceof Date).toBeTrue();
+    const obj = await new Parse.Query('MyClass').first({ useMasterKey: true });
+    expect(obj.get('date')[0] instanceof Date).toBeTrue();
+    expect(obj.get('bar').date[0] instanceof Date).toBeTrue();
+    expect(obj.get('foo').test.date[0] instanceof Date).toBeTrue();
   });
 
   it('handles updating a single object with array, object date', done => {
diff --git a/spec/ParseLiveQueryRedis.spec.js b/spec/ParseLiveQueryRedis.spec.js
index 3187d23cc8..deb84bafb2 100644
--- a/spec/ParseLiveQueryRedis.spec.js
+++ b/spec/ParseLiveQueryRedis.spec.js
@@ -6,6 +6,7 @@ if (process.env.PARSE_SERVER_TEST_CACHE === 'redis') {
     });
     it('can connect', async () => {
       await reconfigureServer({
+        appId: 'redis_live_query',
         startLiveQueryServer: true,
         liveQuery: {
           classNames: ['TestObject'],
@@ -36,6 +37,7 @@ if (process.env.PARSE_SERVER_TEST_CACHE === 'redis') {
 
     it('can call connect twice', async () => {
       const server = await reconfigureServer({
+        appId: 'redis_live_query',
         startLiveQueryServer: true,
         liveQuery: {
           classNames: ['TestObject'],
diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js
index 5b4690ae85..50f29d0aab 100644
--- a/spec/ParseLiveQueryServer.spec.js
+++ b/spec/ParseLiveQueryServer.spec.js
@@ -115,6 +115,7 @@ describe('ParseLiveQueryServer', function () {
   });
 
   describe_only_db('mongo')('initialization', () => {
+    beforeEach(() => reconfigureServer({ appId: 'mongo_init_test' }));
     it('can be initialized through ParseServer without liveQueryServerOptions', async () => {
       const parseServer = await ParseServer.startApp({
         appId: 'hello',
@@ -754,6 +755,49 @@ describe('ParseLiveQueryServer', function () {
     parseLiveQueryServer._onAfterSave(message);
   });
 
+  it('sends correct object for dates', async () => {
+    jasmine.restoreLibrary('../lib/LiveQuery/QueryTools', 'matchesQuery');
+
+    const parseLiveQueryServer = new ParseLiveQueryServer({});
+
+    const date = new Date();
+    const message = {
+      currentParseObject: {
+        date: { __type: 'Date', iso: date.toISOString() },
+        __type: 'Object',
+        key: 'value',
+        className: testClassName,
+      },
+    };
+    // Add mock client
+    const clientId = 1;
+    const client = addMockClient(parseLiveQueryServer, clientId);
+
+    const requestId2 = 2;
+
+    await addMockSubscription(parseLiveQueryServer, clientId, requestId2);
+
+    parseLiveQueryServer._matchesACL = function () {
+      return Promise.resolve(true);
+    };
+
+    parseLiveQueryServer._inflateParseObject(message);
+    parseLiveQueryServer._onAfterSave(message);
+
+    // Make sure we send leave and enter command to client
+    await timeout();
+
+    expect(client.pushCreate).toHaveBeenCalledWith(
+      requestId2,
+      {
+        className: 'TestObject',
+        key: 'value',
+        date: { __type: 'Date', iso: date.toISOString() },
+      },
+      null
+    );
+  });
+
   it('can handle object save command which does not match any subscription', async done => {
     const parseLiveQueryServer = new ParseLiveQueryServer({});
     // Make mock request message
@@ -1138,8 +1182,7 @@ describe('ParseLiveQueryServer', function () {
     expect(toSend.original).toBeUndefined();
     expect(spy).toHaveBeenCalledWith({
       usage: 'Subscribing using fields parameter',
-      solution:
-        `Subscribe using "keys" instead.`,
+      solution: `Subscribe using "keys" instead.`,
     });
   });
 
@@ -1945,6 +1988,7 @@ describe('ParseLiveQueryServer', function () {
     } else {
       subscription.clientRequestIds = new Map([[clientId, [requestId]]]);
     }
+    subscription.query = query.where;
     return subscription;
   }
 
diff --git a/spec/PostgresConfigParser.spec.js b/spec/PostgresConfigParser.spec.js
index 412e7b20b9..f4efc42114 100644
--- a/spec/PostgresConfigParser.spec.js
+++ b/spec/PostgresConfigParser.spec.js
@@ -27,13 +27,13 @@ const baseURI = 'postgres://username:password@localhost:5432/db-name';
 const testfile = fs.readFileSync('./Dockerfile').toString();
 const dbOptionsTest = {};
 dbOptionsTest[
-  `${baseURI}?ssl=true&binary=true&application_name=app_name&fallback_application_name=f_app_name&poolSize=10`
+  `${baseURI}?ssl=true&binary=true&application_name=app_name&fallback_application_name=f_app_name&poolSize=12`
 ] = {
   ssl: true,
   binary: true,
   application_name: 'app_name',
   fallback_application_name: 'f_app_name',
-  poolSize: 10,
+  max: 12,
 };
 dbOptionsTest[`${baseURI}?ssl=&binary=aa`] = {
   binary: false,
@@ -83,6 +83,20 @@ describe('PostgresConfigParser.getDatabaseOptionsFromURI', () => {
   it('sets the poolSize to 10 if the it is not a number', () => {
     const result = parser.getDatabaseOptionsFromURI(`${baseURI}?poolSize=sdf`);
 
-    expect(result.poolSize).toEqual(10);
+    expect(result.max).toEqual(10);
+  });
+
+  it('sets the max to 10 if the it is not a number', () => {
+    const result = parser.getDatabaseOptionsFromURI(`${baseURI}?&max=sdf`);
+
+    expect(result.poolSize).toBeUndefined();
+    expect(result.max).toEqual(10);
+  });
+
+  it('max should take precedence over poolSize', () => {
+    const result = parser.getDatabaseOptionsFromURI(`${baseURI}?poolSize=20&max=12`);
+
+    expect(result.poolSize).toBeUndefined();
+    expect(result.max).toEqual(12);
   });
 });
diff --git a/spec/RateLimit.spec.js b/spec/RateLimit.spec.js
index 10bc127719..894c8fcf82 100644
--- a/spec/RateLimit.spec.js
+++ b/spec/RateLimit.spec.js
@@ -1,3 +1,4 @@
+const RedisCacheAdapter = require('../lib/Adapters/Cache/RedisCacheAdapter').default;
 describe('rate limit', () => {
   it('can limit cloud functions', async () => {
     Parse.Cloud.define('test', () => 'Abc');
@@ -388,4 +389,33 @@ describe('rate limit', () => {
       })
     ).toBeRejectedWith(`Invalid rate limit option "path"`);
   });
+  describe_only(() => {
+    return process.env.PARSE_SERVER_TEST_CACHE === 'redis';
+  })('with RedisCache', function () {
+    it('does work with cache', async () => {
+      await reconfigureServer({
+        rateLimit: [
+          {
+            requestPath: '/classes/*',
+            requestTimeWindow: 10000,
+            requestCount: 1,
+            errorResponseMessage: 'Too many requests',
+            includeInternalRequests: true,
+            redisUrl: 'redis://localhost:6379',
+          },
+        ],
+      });
+      const obj = new Parse.Object('Test');
+      await obj.save();
+      await expectAsync(obj.save()).toBeRejectedWith(
+        new Parse.Error(Parse.Error.CONNECTION_FAILED, 'Too many requests')
+      );
+      const cache = new RedisCacheAdapter();
+      await cache.connect();
+      const value = await cache.get('rl:127.0.0.1');
+      expect(value).toEqual(2);
+      const ttl = await cache.client.ttl('rl:127.0.0.1');
+      expect(ttl).toEqual(10);
+    });
+  });
 });
diff --git a/spec/helper.js b/spec/helper.js
index 445a137ac5..445de26509 100644
--- a/spec/helper.js
+++ b/spec/helper.js
@@ -198,6 +198,10 @@ beforeAll(async () => {
   Parse.serverURL = 'http://localhost:' + port + '/1';
 });
 
+beforeEach(() => {
+  jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 10000;
+});
+
 afterEach(function (done) {
   const afterLogOut = async () => {
     if (Object.keys(openConnections).length > 0) {
@@ -214,6 +218,7 @@ afterEach(function (done) {
     done();
   };
   Parse.Cloud._removeAllHooks();
+  Parse.CoreManager.getLiveQueryController().setDefaultLiveQueryClient();
   defaults.protectedFields = { _User: { '*': ['email'] } };
   databaseAdapter
     .getAllClasses()
diff --git a/spec/index.spec.js b/spec/index.spec.js
index 64c4b54db7..08ef16a77b 100644
--- a/spec/index.spec.js
+++ b/spec/index.spec.js
@@ -558,7 +558,7 @@ describe('server', () => {
   });
 
   it('can get starting state', async () => {
-    await reconfigureServer({ appId: 'test2', silent: false });
+    await reconfigureServer({ appId: 'test2' });
     const parseServer = new ParseServer.ParseServer({
       ...defaultConfiguration,
       appId: 'test2',
diff --git a/src/Adapters/Analytics/AnalyticsAdapter.js b/src/Adapters/Analytics/AnalyticsAdapter.js
index 3fd50242d9..e3cced14f5 100644
--- a/src/Adapters/Analytics/AnalyticsAdapter.js
+++ b/src/Adapters/Analytics/AnalyticsAdapter.js
@@ -1,9 +1,7 @@
 /*eslint no-unused-vars: "off"*/
-/**
- * @module Adapters
- */
 /**
  * @interface AnalyticsAdapter
+ * @module Adapters
  */
 export class AnalyticsAdapter {
   /**
diff --git a/src/Adapters/Auth/AuthAdapter.js b/src/Adapters/Auth/AuthAdapter.js
index 0e106014d5..5b18c75170 100644
--- a/src/Adapters/Auth/AuthAdapter.js
+++ b/src/Adapters/Auth/AuthAdapter.js
@@ -93,6 +93,24 @@ export class AuthAdapter {
   challenge(challengeData, authData, options, request) {
     return Promise.resolve({});
   }
+
+  /**
+   * Triggered when auth data is fetched
+   * @param {Object} authData authData
+   * @param {Object} options additional adapter options
+   * @returns {Promise