diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn
index 608237347ebc99857d7643229bc6c1086529f16e..0a82507db117b108f50a33bfdfc6ceab027c4e97 100644
--- a/.clj-kondo/config.edn
+++ b/.clj-kondo/config.edn
@@ -353,6 +353,7 @@
     metabase.util.i18n                                              i18n
     metabase.util.i18n.impl                                         i18n.impl
     metabase.util.malli                                             mu
+    metabase.util.malli.schema                                      ms
     metabase.util.password                                          u.password
     metabase.util.schema                                            su
     metabase.util.ui-logic                                          ui-logic
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj
index 694b7b4992e08961cdec601583ff832c518fb071..89e7bbe38189e7a0eb343eddfdb20833d18c5691 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj
@@ -91,7 +91,7 @@
     - Permissions have three levels: full, limited, and none.
     - Native query download permissions are fully inferred from the non-native download permissions. For more details,
       see the docstring for [[metabase.models.permissions/update-native-download-permissions!]]."
-  [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-download-perms :- perms/DownloadPermissionsGraph]
+  [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-download-perms :- perms/DownloadPermissionsGraph]
   (when-not (premium-features/enable-advanced-permissions?)
     (throw (perms/ee-permissions-exception :download)))
   (when-let [schemas (:schemas new-download-perms)]
@@ -157,7 +157,7 @@
 
 (s/defn update-db-data-model-permissions!
   "Update the data model permissions graph for a database."
-  [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-data-model-perms :- perms/DataModelPermissionsGraph]
+  [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-data-model-perms :- perms/DataModelPermissionsGraph]
   (when-not (premium-features/enable-advanced-permissions?)
     (throw (perms/ee-permissions-exception :data-model)))
   (when-let [schemas (:schemas new-data-model-perms)]
@@ -188,7 +188,7 @@
 
 (s/defn update-db-details-permissions!
   "Update the DB details permissions for a database."
-  [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-perms :- perms/DetailsPermissions]
+  [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-perms :- perms/DetailsPermissions]
   (when-not (premium-features/enable-advanced-permissions?)
     (throw (perms/ee-permissions-exception :details)))
   (case new-perms
@@ -202,7 +202,7 @@
 
 (s/defn update-db-execute-permissions!
   "Update the DB details permissions for a database."
-  [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-perms :- perms/ExecutePermissions]
+  [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-perms :- perms/ExecutePermissions]
   (when-not (premium-features/enable-advanced-permissions?)
     (throw (perms/ee-permissions-exception :execute)))
   (revoke-permissions! :execute :all group-id db-id)
diff --git a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj
index 1721ec42ee7a37c596aa3fdb2750416798193d43..b7cba0a968540caa06c27367175ce9ce17e3720c 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj
@@ -18,7 +18,7 @@
 
 (def ^:private ApplicationPermissionsGraph
   {:revision s/Int
-   :groups   {su/IntGreaterThanZeroPlumatic GroupPermissionsGraph}})
+   :groups   {su/IntGreaterThanZero GroupPermissionsGraph}})
 
 ;; -------------------------------------------------- Fetch Graph ---------------------------------------------------
 
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj b/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj
index d53e27f32bbe59878049d467a91e021b86252ef8..e4e6ae53d97e24a00a73c3df2fce377b9a00986c 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj
@@ -8,8 +8,8 @@
 (def ResultsMetadata
   "Schema for the expected format for `:metadata` returned by an internal query function."
   (su/non-empty
-   [[(s/one su/KeywordOrStringPlumatic "field name")
-     (s/one {:base_type su/FieldTypePlumatic, :display_name su/NonBlankStringPlumatic, s/Keyword s/Any}
+   [[(s/one su/KeywordOrString "field name")
+     (s/one {:base_type su/FieldType, :display_name su/NonBlankString, s/Keyword s/Any}
             "field metadata")]]))
 
 (defmulti internal-query
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj
index d9e1633cfc8bab711cf7994dc6e9a7165d4867bc..071f64cb77c1d02989fe0d928501d2bad4d7911f 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj
@@ -22,7 +22,7 @@
 ;; ORDER BY {{group-fn(timestamp}} ASC
 (s/defn views-by-time
   "Get views of a Card or Dashboard broken out by a time `unit`, e.g. `day` or `day-of-week`."
-  [model :- ModelName, model-id :- su/IntGreaterThanZeroPlumatic, unit :- common/DateTimeUnitStr]
+  [model :- ModelName, model-id :- su/IntGreaterThanZero, unit :- common/DateTimeUnitStr]
   {:metadata [[:date  {:display_name "Date",  :base_type (common/datetime-unit-str->base-type unit)}]
               [:views {:display_name "Views", :base_type :type/Integer}]]
    :results (let [grouped-timestamp (common/grouped-datetime unit :timestamp)]
@@ -40,7 +40,7 @@
 (s/defn cached-views-by-time
   "Get number of views of a Card broken out by a time `unit`, e.g. `day` or `day-of-week` and by cache status.
   Still here instead of in cards because of similarity to views-by-time"
-  [card-id :- su/IntGreaterThanZeroPlumatic, unit :- common/DateTimeUnitStr]
+  [card-id :- su/IntGreaterThanZero, unit :- common/DateTimeUnitStr]
   {:metadata [[:date           {:display_name "Date",
                                 :base_type (common/datetime-unit-str->base-type unit)}]
               [:cached-views   {:display_name "Cached Views",
@@ -64,7 +64,7 @@
 (s/defn avg-execution-time-by-time
   "Get average execution time of a Card broken out by a time `unit`, e.g. `day` or `day-of-week`.
   Still here instead of in cards because of similarity to views-by-time"
-  [card-id :- su/IntGreaterThanZeroPlumatic, unit :- common/DateTimeUnitStr]
+  [card-id :- su/IntGreaterThanZero, unit :- common/DateTimeUnitStr]
   {:metadata [[:date        {:display_name "Date",            :base_type (common/datetime-unit-str->base-type unit)}]
               [:avg_runtime {:display_name "Average Runtime", :base_type :type/Number}]]
    :results (let [grouped-timestamp (common/grouped-datetime unit :started_at)]
@@ -80,7 +80,7 @@
 (s/defn revision-history
   "Get a revision history table for a Card or Dashboard."
   [model-entity :- (s/cond-pre (mi/InstanceOf Card) (mi/InstanceOf Dashboard))
-   model-id     :- su/IntGreaterThanZeroPlumatic]
+   model-id     :- su/IntGreaterThanZero]
   {:metadata [[:timestamp   {:display_name "Edited on",   :base_type :type/DateTime}]
               [:user_id     {:display_name "User ID",     :base_type :type/Integer, :remapped_to   :user_name}]
               [:user_name   {:display_name "Edited by",   :base_type :type/Name,    :remapped_from :user_id}]
@@ -95,7 +95,7 @@
 
 (s/defn audit-log
   "Get a view log for a Card or Dashboard."
-  [model :- ModelName, model-id :- su/IntGreaterThanZeroPlumatic]
+  [model :- ModelName, model-id :- su/IntGreaterThanZero]
   {:metadata [[:when    {:display_name "When",    :base_type :type/DateTime}]
               [:user_id {:display_name "User ID", :base_type :type/Integer, :remapped_to   :who}]
               [:who     {:display_name "Who",     :base_type :type/Name,    :remapped_from :user_id}]
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj
index 776c93c97713e5e1a7e0e206a4e07c4c7174bdf5..8fb58047290b4958fc89e4621dd5c55be5fc796e 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj
@@ -11,22 +11,22 @@
 
 ;; Get views of a Dashboard broken out by a time `unit`, e.g. `day` or `day-of-week`.
 (s/defmethod audit.i/internal-query ::views-by-time
-  [_ dashboard-id  :- su/IntGreaterThanZeroPlumatic datetime-unit :- common/DateTimeUnitStr]
+  [_ dashboard-id  :- su/IntGreaterThanZero datetime-unit :- common/DateTimeUnitStr]
   (card-and-dash-detail/views-by-time "dashboard" dashboard-id datetime-unit))
 
 ;; Revision history for a specific Dashboard.
 (s/defmethod audit.i/internal-query ::revision-history
-  [_ dashboard-id :- su/IntGreaterThanZeroPlumatic]
+  [_ dashboard-id :- su/IntGreaterThanZero]
   (card-and-dash-detail/revision-history Dashboard dashboard-id))
 
 ;; View log for a specific Dashboard.
 (s/defmethod audit.i/internal-query ::audit-log
-  [_ dashboard-id :- su/IntGreaterThanZeroPlumatic]
+  [_ dashboard-id :- su/IntGreaterThanZero]
   (card-and-dash-detail/audit-log "dashboard" dashboard-id))
 
 ;; Information about the Saved Questions (Cards) in this instance.
 (s/defmethod audit.i/internal-query ::cards
-  [_ dashboard-id :- su/IntGreaterThanZeroPlumatic]
+  [_ dashboard-id :- su/IntGreaterThanZero]
   {:metadata [[:card_id             {:display_name "Card ID",              :base_type :type/Integer, :remapped_to   :card_name}]
               [:card_name           {:display_name "Title",                :base_type :type/Name,    :remapped_from :card_id}]
               [:collection_id       {:display_name "Collection ID",        :base_type :type/Integer, :remapped_to   :collection_name}]
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj
index c5e558d46a91e26c6fc7f7dd030835646e3c4cdf..3016e75fc8814f8c358fd1e6ebf8ae8a968f058b 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj
@@ -8,7 +8,7 @@
 
 ;; Query execution history for queries against this Database.
 (s/defmethod audit.i/internal-query ::audit-log
-  [_ database-id :- su/IntGreaterThanZeroPlumatic]
+  [_ database-id :- su/IntGreaterThanZero]
   {:metadata [[:started_at {:display_name "Viewed on",  :base_type :type/DateTime}]
               [:card_id    {:display_name "Card ID",    :base_type :type/Integer, :remapped_to   :query}]
               [:query_hash {:display_name "Query Hash", :base_type :type/Text}]
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj
index 2febbbaa4de399ac6f65c0c44327cea46580695b..d21419466faab8a8d8d8bcf29d852e57426a70da 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj
@@ -61,7 +61,7 @@
 
 ;; Details about a specific query (currently just average execution time).
 (s/defmethod audit.i/internal-query ::details
-  [_ query-hash :- su/NonBlankStringPlumatic]
+  [_ query-hash :- su/NonBlankString]
   {:metadata [[:query                  {:display_name "Query",                :base_type :type/Dictionary}]
               [:average_execution_time {:display_name "Avg. Exec. Time (ms)", :base_type :type/Number}]]
    :results  (common/reducible-query
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj
index c10f3c5eaec3eeb3bacbc4b575d2226562c92856..713d17f9dc8f73b70a6dd72526046d63e9e804f1 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj
@@ -10,25 +10,25 @@
 
 ;; Get views of a Card broken out by a time `unit`, e.g. `day` or `day-of-week`.
 (s/defmethod audit.i/internal-query ::views-by-time
-  [_ card-id :- su/IntGreaterThanZeroPlumatic datetime-unit :- common/DateTimeUnitStr]
+  [_ card-id :- su/IntGreaterThanZero datetime-unit :- common/DateTimeUnitStr]
   (card-and-dash-detail/views-by-time "card" card-id datetime-unit))
 
 ;; Get cached views of a Card broken out by a time `unit`, e.g. `day` or `day-of-week`.
 (s/defmethod audit.i/internal-query ::cached-views-by-time
-  [_ card-id :- su/IntGreaterThanZeroPlumatic, datetime-unit :- common/DateTimeUnitStr]
+  [_ card-id :- su/IntGreaterThanZero, datetime-unit :- common/DateTimeUnitStr]
   (card-and-dash-detail/cached-views-by-time card-id datetime-unit))
 
 ;; Get the revision history for a Card.
 (s/defmethod audit.i/internal-query ::revision-history
-  [_ card-id :- su/IntGreaterThanZeroPlumatic]
+  [_ card-id :- su/IntGreaterThanZero]
   (card-and-dash-detail/revision-history Card card-id))
 
 ;; Get a view log for a Card.
 (s/defmethod audit.i/internal-query ::audit-log
-  [_ card-id :- su/IntGreaterThanZeroPlumatic]
+  [_ card-id :- su/IntGreaterThanZero]
   (card-and-dash-detail/audit-log "card" card-id))
 
 ;; Average execution time broken out by period
 (s/defmethod audit.i/internal-query ::avg-execution-time-by-time
-  [_ card-id :- su/IntGreaterThanZeroPlumatic datetime-unit :- common/DateTimeUnitStr]
+  [_ card-id :- su/IntGreaterThanZero datetime-unit :- common/DateTimeUnitStr]
   (card-and-dash-detail/avg-execution-time-by-time card-id datetime-unit))
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj
index b0b30a587faa884bb4f04f4b95541db5273764a9..6139bb7210eee4025d3ab8c1a0d5c589c748dc68 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj
@@ -8,7 +8,7 @@
 
 ;; View log for a specific Table.
 (s/defmethod audit.i/internal-query ::audit-log
-  [_ table-id :- su/IntGreaterThanZeroPlumatic]
+  [_ table-id :- su/IntGreaterThanZero]
   {:metadata [[:started_at {:display_name "Viewed on",  :base_type :type/DateTime}]
               [:card_id    {:display_name "Card ID",    :base_type :type/Integer, :remapped_to   :query}]
               [:query      {:display_name "Query",      :base_type :type/Text,    :remapped_from :card_id}]
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj
index 3d09bc57cec639203a029ad08ec519b65a310ab6..b67dbdba003282979f0c4a17b5f629979b8c1ff1 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj
@@ -16,7 +16,7 @@
 ;;
 ;; (TODO - in the designs, this is pivoted; should we do that here in Clojure-land?)
 (s/defmethod audit.i/internal-query ::table
-  [_ user-id :- su/IntGreaterThanZeroPlumatic]
+  [_ user-id :- su/IntGreaterThanZero]
   {:metadata [[:name             {:display_name "Name",             :base_type :type/Name}]
               [:role             {:display_name "Role",             :base_type :type/Text}]
               [:groups           {:display_name "Groups",           :base_type :type/Text}]
@@ -79,7 +79,7 @@
 
 ;; Return the 10 most-viewed Dashboards for a given User, in descending order.
 (s/defmethod audit.i/internal-query ::most-viewed-dashboards
-  [_ user-id :- su/IntGreaterThanZeroPlumatic]
+  [_ user-id :- su/IntGreaterThanZero]
   {:metadata [[:dashboard_id   {:display_name "Dashboard ID", :base_type :type/Integer, :remapped_to   :dashboard_name}]
               [:dashboard_name {:display_name "Dashboard",    :base_type :type/Name,    :remapped_from :dashboard_id}]
               [:count          {:display_name "Views",        :base_type :type/Integer}]]
@@ -98,7 +98,7 @@
 
 ;; Return the 10 most-viewed Questions for a given User, in descending order.
 (s/defmethod audit.i/internal-query ::most-viewed-questions
-  [_ user-id :- su/IntGreaterThanZeroPlumatic]
+  [_ user-id :- su/IntGreaterThanZero]
   {:metadata [[:card_id   {:display_name "Card ID", :base_type :type/Integer, :remapped_to   :card_name}]
               [:card_name {:display_name "Query",   :base_type :type/Name,    :remapped_from :card_id}]
               [:count     {:display_name "Views",   :base_type :type/Integer}]]
@@ -117,7 +117,7 @@
 
 ;; Query views by a specific User.
 (s/defmethod audit.i/internal-query ::query-views
-  [_ user-id :- su/IntGreaterThanZeroPlumatic]
+  [_ user-id :- su/IntGreaterThanZero]
   {:metadata [[:viewed_on     {:display_name "Viewed On",      :base_type :type/DateTime}]
               [:card_id       {:display_name "Card ID"         :base_type :type/Integer, :remapped_to   :card_name}]
               [:card_name     {:display_name "Query",          :base_type :type/Text,    :remapped_from :card_id}]
@@ -157,7 +157,7 @@
 
 ;; Dashboard views by a specific User.
 (s/defmethod audit.i/internal-query ::dashboard-views
-  [_ user-id :- su/IntGreaterThanZeroPlumatic]
+  [_ user-id :- su/IntGreaterThanZero]
   {:metadata [[:timestamp       {:display_name "Viewed on",     :base_type :type/DateTime}]
               [:dashboard_id    {:display_name "Dashboard ID",  :base_type :type/Integer, :remapped_to   :dashboard_name}]
               [:dashboard_name  {:display_name "Dashboard",     :base_type :type/Text,    :remapped_from :dashboard_id}]
@@ -180,7 +180,7 @@
 ;; Timeseries chart that shows the number of Question or Dashboard views for a User, broken out by `datetime-unit`.
 (s/defmethod audit.i/internal-query ::object-views-by-time
   [_
-   user-id       :- su/IntGreaterThanZeroPlumatic
+   user-id       :- su/IntGreaterThanZero
    model         :- (s/enum "card" "dashboard")
    datetime-unit :- common/DateTimeUnitStr]
   {:metadata [[:date {:display_name "Date",   :base_type (common/datetime-unit-str->base-type datetime-unit)}]
@@ -199,12 +199,12 @@
 (s/defmethod audit.i/internal-query ::created-dashboards
   ([query-type user-id]
    (audit.i/internal-query query-type user-id nil))
-  ([_ user-id :- su/IntGreaterThanZeroPlumatic query-string :- (s/maybe s/Str)]
+  ([_ user-id :- su/IntGreaterThanZero query-string :- (s/maybe s/Str)]
    (dashboards/table query-string [:= :u.id user-id])))
 
 ;; Questions created by a specific User.
 (s/defmethod audit.i/internal-query ::created-questions
-  [_ user-id :- su/IntGreaterThanZeroPlumatic]
+  [_ user-id :- su/IntGreaterThanZero]
   {:metadata [[:card_id             {:display_name "Card ID",              :base_type :type/Integer, :remapped_to   :card_name}]
               [:card_name           {:display_name "Title",                :base_type :type/Name,    :remapped_from :card_id}]
               [:collection_id       {:display_name "Collection ID",        :base_type :type/Integer, :remapped_to   :collection_name}]
@@ -249,7 +249,7 @@
 ;; Table of query downloads (i.e., queries whose results are returned as CSV/JSON/XLS) done by this user, ordered by
 ;; most recent.
 (s/defmethod audit.i/internal-query ::downloads
-  [_ user-id :- su/IntGreaterThanZeroPlumatic]
+  [_ user-id :- su/IntGreaterThanZero]
   {:metadata [[:downloaded_at   {:display_name "Downloaded At",   :base_type :type/DateTime}]
               [:rows_downloaded {:display_name "Rows Downloaded", :base_type :type/Integer}]
               [:card_id         {:display_name "Card ID",         :base_type :type/Integer, :remapped_to :card_name}]
diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj b/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj
index a49c2962079b806b11068a7c1f74efe1530cf239..6442bc6e214575f64c17ee5c7ff7a03263d37cd9 100644
--- a/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj
+++ b/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj
@@ -68,7 +68,7 @@
   (for [[k v] metadata]
     (assoc v :name (name k))))
 
-(s/defn ^:private format-results [{:keys [results metadata]} :- {:results  [su/MapPlumatic]
+(s/defn ^:private format-results [{:keys [results metadata]} :- {:results  [su/Map]
                                                                  :metadata audit.i/ResultsMetadata}]
   (check-results-and-metadata-keys-match results metadata)
   {:cols (metadata->cols metadata)
diff --git a/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj b/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj
index 90d33305432cfe2a80bf8eee1568ee469313201d..e7dc37e8e22b4426963d38b490361c3e4a5e3756 100644
--- a/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj
+++ b/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj
@@ -12,7 +12,7 @@
   "Create a new `ModerationReview`."
   [:as {{:keys [text moderated_item_id moderated_item_type status]} :body}]
   {text                (s/maybe s/Str)
-   moderated_item_id   su/IntGreaterThanZeroPlumatic
+   moderated_item_id   su/IntGreaterThanZero
    moderated_item_type moderation/moderated-item-types
    status              moderation-review/Statuses}
   (api/check-superuser)
diff --git a/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj b/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj
index 9f7f8fb5dd70af21cdb5cd16227be7139f242533..8890f8eed20594333ddece5af074af66ba0524a8 100644
--- a/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj
+++ b/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj
@@ -63,7 +63,7 @@
   "Get user information for the supplied username."
   :feature :any
   [ldap-connection :- LDAPConnectionPool
-   username        :- su/NonBlankStringPlumatic
+   username        :- su/NonBlankString
    settings        :- i/LDAPSettings]
   (when-let [result (default-impl/search ldap-connection username settings)]
     (when-let [user-info (default-impl/ldap-search-result->user-info
diff --git a/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj b/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj
index 9f61cac8fee3c75185fdf582c63d323b3ceabe75..affd3bd4035e432a543de45b5a2d73427a1ec7d6 100644
--- a/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj
+++ b/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj
@@ -9,7 +9,7 @@
    [toucan.db :as db]))
 
 (s/defn ^:private has-parent-collection-perms?
-  [snippet       :- {:collection_id (s/maybe su/IntGreaterThanZeroPlumatic), s/Keyword s/Any}
+  [snippet       :- {:collection_id (s/maybe su/IntGreaterThanZero), s/Keyword s/Any}
    read-or-write :- (s/enum :read :write)]
   (mi/current-user-has-full-permissions? (perms/perms-objects-set-for-parent-collection "snippets" snippet read-or-write)))
 
diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj b/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj
index 3d2f8001e1ec4867163f7ef47cd2302ffff8d689..963fec6008645a9a8051be7e4792910968b03c28 100644
--- a/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj
+++ b/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj
@@ -36,9 +36,9 @@
 (api/defendpoint-schema POST "/"
   "Create a new GTAP."
   [:as {{:keys [table_id card_id group_id attribute_remappings]} :body}]
-  {table_id             su/IntGreaterThanZeroPlumatic
-   card_id              (s/maybe su/IntGreaterThanZeroPlumatic)
-   group_id             su/IntGreaterThanZeroPlumatic
+  {table_id             su/IntGreaterThanZero
+   card_id              (s/maybe su/IntGreaterThanZero)
+   group_id             su/IntGreaterThanZero
    #_attribute_remappings #_AttributeRemappings} ; TODO -  fix me
   (db/insert! GroupTableAccessPolicy
     {:table_id             table_id
@@ -52,7 +52,7 @@
   paramter mappings; changing `table_id` or `group_id` would effectively be deleting this entry and creating a new
   one. If that's what you want to do, do so explicity with appropriate calls to the `DELETE` and `POST` endpoints."
   [id :as {{:keys [card_id #_attribute_remappings], :as body} :body}]
-  {card_id              (s/maybe su/IntGreaterThanZeroPlumatic)
+  {card_id              (s/maybe su/IntGreaterThanZero)
    #_attribute_remappings #_AttributeRemappings} ; TODO -  fix me
   (api/check-404 (GroupTableAccessPolicy id))
   ;; Only update `card_id` and/or `attribute_remappings` if the values are present in the body of the request.
diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj b/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj
index bffde827db27e3a27b901a48a0893842c6071767..83f8f63450a9310dc0ba8708d82cae3257a490e3 100644
--- a/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj
+++ b/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj
@@ -61,9 +61,9 @@
   doesn't add/change anything from the OSS version. See the docs on the OSS version of the endpoint for more
   information."
   [id include_sensitive_fields include_hidden_fields include_editable_data_model]
-  {include_sensitive_fields    (s/maybe su/BooleanStringPlumatic)
-   include_hidden_fields       (s/maybe su/BooleanStringPlumatic)
-   include_editable_data_model (s/maybe su/BooleanStringPlumatic)}
+  {include_sensitive_fields    (s/maybe su/BooleanString)
+   include_hidden_fields       (s/maybe su/BooleanString)
+   include_editable_data_model (s/maybe su/BooleanString)}
   (let [table            (api/check-404 (db/select-one Table :id id))
         segmented-perms? (only-segmented-perms? table)
         thunk            (fn []
diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj b/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj
index 5f29d6b872387e9fa310ac184c4197853dafe8d9..b9232dcae262e7a6cc4827cc96a5eb70ef71aff8 100644
--- a/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj
+++ b/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj
@@ -10,7 +10,7 @@
    [toucan.db :as db]))
 
 (def ^:private UserAttributes
-  (su/with-api-error-message (s/maybe {su/NonBlankStringPlumatic s/Any})
+  (su/with-api-error-message (s/maybe {su/NonBlankString s/Any})
     "value must be a valid user attributes map (name -> value)"))
 
 ;; TODO - not sure we need this endpoint now that we're just letting you edit from the regular `PUT /api/user/:id
diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj b/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj
index fee61b05f4541def03e8046ebe68c51ae6a125f5..b10b0a19cc262a6bc75fe25cda53054939d384d4 100644
--- a/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj
+++ b/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj
@@ -93,7 +93,7 @@
      (when-let [result-metadata (db/select-one-field :result_metadata Card :id card-id)]
        (check-columns-match-table table-id result-metadata))))
 
-  ([table-id :- su/IntGreaterThanZeroPlumatic result-metadata-columns]
+  ([table-id :- su/IntGreaterThanZero result-metadata-columns]
    ;; prevent circular refs
    (classloader/require 'metabase.query-processor)
    (let [table-cols (table-field-names->cols table-id)]
diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj b/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj
index df372650dc5bedee381f9ce8d95ab6eeacf0cd6b..c768c848efb7c8e1ac10b0fc3418ea8e92a2f6e1 100644
--- a/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj
+++ b/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj
@@ -96,7 +96,7 @@
 ;;; |                                                Applying a GTAP                                                 |
 ;;; +----------------------------------------------------------------------------------------------------------------+
 
-(s/defn ^:private target-field->base-type :- (s/maybe su/FieldTypePlumatic)
+(s/defn ^:private target-field->base-type :- (s/maybe su/FieldType)
   "If the `:target` of a parameter contains a `:field` clause, return the base type corresponding to the Field it
   references. Otherwise returns `nil`."
   [[_ target-field-clause]]
@@ -160,7 +160,7 @@
 (defn- table-gtap->source [{table-id :table_id, :as gtap}]
   {:source-query {:source-table table-id, :parameters (gtap->parameters gtap)}})
 
-(s/defn ^:private mbql-query-metadata :- (su/non-empty [su/MapPlumatic])
+(s/defn ^:private mbql-query-metadata :- (su/non-empty [su/Map])
   [inner-query]
   (binding [api/*current-user-permissions-set* (atom #{"/"})]
     ((requiring-resolve 'metabase.query-processor/query->expected-cols)
@@ -177,9 +177,9 @@
      (mbql-query-metadata {:source-table table-id}))
    :ttl/threshold (u/minutes->ms 1)))
 
-(s/defn ^:private reconcile-metadata :- (su/non-empty [su/MapPlumatic])
+(s/defn ^:private reconcile-metadata :- (su/non-empty [su/Map])
   "Combine the metadata in `source-query-metadata` with the `table-metadata` from the Table being sandboxed."
-  [source-query-metadata :- (su/non-empty [su/MapPlumatic]) table-metadata]
+  [source-query-metadata :- (su/non-empty [su/Map]) table-metadata]
   (let [col-name->table-metadata (m/index-by :name table-metadata)]
     (vec
      (for [col   source-query-metadata
@@ -189,7 +189,7 @@
          (gtap/check-column-types-match col table-col)
          table-col)))))
 
-(s/defn ^:private native-query-metadata :- (su/non-empty [su/MapPlumatic])
+(s/defn ^:private native-query-metadata :- (su/non-empty [su/Map])
   [source-query :- {:source-query s/Any, s/Keyword s/Any}]
   (let [result (binding [api/*current-user-permissions-set* (atom #{"/"})]
                  ((requiring-resolve 'metabase.query-processor/process-query)
@@ -203,13 +203,13 @@
                          :result       result})))))
 
 (s/defn ^:private source-query-form-ensure-metadata :- {:source-query    s/Any
-                                                        :source-metadata (su/non-empty [su/MapPlumatic])
+                                                        :source-metadata (su/non-empty [su/Map])
                                                         s/Keyword        s/Any}
   "Add `:source-metadata` to a `source-query` if needed. If the source metadata had to be resolved (because Card with
   `card-id`) didn't already have it, save it so we don't have to resolve it again next time around."
   [{:keys [source-metadata], :as source-query} :- {:source-query s/Any, s/Keyword s/Any}
-   table-id                                    :- su/IntGreaterThanZeroPlumatic
-   card-id                                     :- (s/maybe su/IntGreaterThanZeroPlumatic)]
+   table-id                                    :- su/IntGreaterThanZero
+   card-id                                     :- (s/maybe su/IntGreaterThanZero)]
   (let [table-metadata   (original-table-metadata table-id)
         ;; make sure source query has `:source-metadata`; add it if needed
         [metadata save?] (cond
@@ -242,7 +242,7 @@
                                    (s/optional-key :source-metadata) [mbql.s/SourceQueryMetadata]
                                    s/Keyword                         s/Any}
   "Get the source query associated with a `gtap`."
-  [{card-id :card_id, table-id :table_id, :as gtap} :- su/MapPlumatic]
+  [{card-id :card_id, table-id :table_id, :as gtap} :- su/Map]
   (-> ((if card-id
          card-gtap->source
          table-gtap->source) gtap)
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj b/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj
index de73002134f5f13417619d62b46c8d23e7789089..e207e30c014ef886ccc937cb29edabbaa33d2b1a 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj
@@ -24,9 +24,9 @@
   - The collections that they want to serialize (using selective serialization)"
   [:as {{:keys [collection_ids path]} :body}]
   {collection_ids (su/with-api-error-message
-                    (su/distinct (su/non-empty [su/IntGreaterThanZeroPlumatic]))
+                    (su/distinct (su/non-empty [su/IntGreaterThanZero]))
                     "Non-empty, distinct array of Collection IDs")
-   path           (su/with-api-error-message su/NonBlankStringPlumatic
+   path           (su/with-api-error-message su/NonBlankString
                     "Valid directory to serialize results to")}
   ;; Make sure all the specified collection IDs exist.
   (let [existing-collection-ids (db/select-ids Collection :id [:in (set collection_ids)])]
diff --git a/enterprise/backend/src/metabase_enterprise/serialization/names.clj b/enterprise/backend/src/metabase_enterprise/serialization/names.clj
index 1dc957df56dc1c764a379b263c0cbc4c26574f2a..3f760c09265cf058aaa8071056195da1c091bc11 100644
--- a/enterprise/backend/src/metabase_enterprise/serialization/names.clj
+++ b/enterprise/backend/src/metabase_enterprise/serialization/names.clj
@@ -129,18 +129,18 @@
 
 ;; All the references in the dumps should resolved to entities already loaded.
 (def ^:private Context
-  {(s/optional-key :database)   su/IntGreaterThanZeroPlumatic
-   (s/optional-key :table)      su/IntGreaterThanZeroPlumatic
+  {(s/optional-key :database)   su/IntGreaterThanZero
+   (s/optional-key :table)      su/IntGreaterThanZero
    (s/optional-key :schema)     (s/maybe s/Str)
-   (s/optional-key :field)      su/IntGreaterThanZeroPlumatic
-   (s/optional-key :metric)     su/IntGreaterThanZeroPlumatic
-   (s/optional-key :segment)    su/IntGreaterThanZeroPlumatic
-   (s/optional-key :card)       su/IntGreaterThanZeroPlumatic
-   (s/optional-key :dashboard)  su/IntGreaterThanZeroPlumatic
-   (s/optional-key :collection) (s/maybe su/IntGreaterThanZeroPlumatic) ; root collection
-   (s/optional-key :pulse)      su/IntGreaterThanZeroPlumatic
-   (s/optional-key :user)       su/IntGreaterThanZeroPlumatic
-   (s/optional-key :snippet)    (s/maybe su/IntGreaterThanZeroPlumatic)})
+   (s/optional-key :field)      su/IntGreaterThanZero
+   (s/optional-key :metric)     su/IntGreaterThanZero
+   (s/optional-key :segment)    su/IntGreaterThanZero
+   (s/optional-key :card)       su/IntGreaterThanZero
+   (s/optional-key :dashboard)  su/IntGreaterThanZero
+   (s/optional-key :collection) (s/maybe su/IntGreaterThanZero) ; root collection
+   (s/optional-key :pulse)      su/IntGreaterThanZero
+   (s/optional-key :user)       su/IntGreaterThanZero
+   (s/optional-key :snippet)    (s/maybe su/IntGreaterThanZero)})
 
 (defmulti ^:private path->context* (fn [_ model _ _]
                                      model))
diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
index 897881402721ba60c85c7800fc3ee4e5d947defb..52c401bbf84f0d7e7854a4f9ae734640723ab72d 100644
--- a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
+++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
@@ -11,7 +11,7 @@
    [schema.core :as s]))
 
 (def ^:private GroupMappings
-  (s/maybe {su/KeywordOrStringPlumatic [su/IntGreaterThanZeroPlumatic]}))
+  (s/maybe {su/KeywordOrString [su/IntGreaterThanZero]}))
 
 (def ^:private ^{:arglists '([group-mappings])} validate-group-mappings
   (s/validator GroupMappings))
diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj
index 4bbc648083cb51f9ec4e0524114604f7fba93eb7..cffff9bd3fc87e14c88a6e0d55faea2f49b4581d 100644
--- a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj
+++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj
@@ -17,9 +17,9 @@
    (java.util UUID)))
 
 (def ^:private UserAttributes
-  {:first_name       (s/maybe su/NonBlankStringPlumatic)
-   :last_name        (s/maybe su/NonBlankStringPlumatic)
-   :email            su/EmailPlumatic
+  {:first_name       (s/maybe su/NonBlankString)
+   :last_name        (s/maybe su/NonBlankString)
+   :email            su/Email
    ;; TODO - we should avoid hardcoding this to make it easier to add new integrations. Maybe look at something like
    ;; the keys of `(methods sso/sso-get)`
    :sso_source       (s/enum "saml" "jwt")
diff --git a/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj b/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj
index 9f5e02f1cc095efeef068c2f6462757856b38e6d..778bea6908ab2c5d4ace79c4b9790a830cb58941 100644
--- a/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj
+++ b/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj
@@ -175,7 +175,7 @@
                             s/Keyword s/Any}
                            (ldap/fetch-or-create-user! user-info))))
             (testing "Call fetch-or-create-user! again to trigger update"
-              (is (schema= {:id su/IntGreaterThanZeroPlumatic,  s/Keyword s/Any}
+              (is (schema= {:id su/IntGreaterThanZero,  s/Keyword s/Any}
                            (ldap/fetch-or-create-user! (assoc-in user-info [:attributes :unladenspeed] 100)))))
             (is (= {:first_name       "John"
                     :last_name        "Smith"
@@ -201,7 +201,7 @@
                               s/Keyword s/Any}
                              (ldap/fetch-or-create-user! user-info))))
               (testing "Call fetch-or-create-user! again to trigger update"
-                (is (schema= {:id su/IntGreaterThanZeroPlumatic,  s/Keyword s/Any}
+                (is (schema= {:id su/IntGreaterThanZero,  s/Keyword s/Any}
                              (ldap/fetch-or-create-user! (assoc-in user-info [:attributes :unladenspeed] 100)))))
               (is (= {:first_name       "John"
                       :last_name        "Smith"
diff --git a/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj b/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj
index 0a46b782e09cef810f8be91ab24ef439bba86886..1cab256e11a90d7c105d4ce0a4c5155c4a267d54 100644
--- a/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj
+++ b/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj
@@ -69,7 +69,7 @@
                        (get-in (mt/user-http-request :crowberto :get 200 "permissions/graph")
                                (venues-perms-graph-keypath &group)))))
               (testing "GTAP should exist in application DB"
-                (is (schema= [(s/one {:id                   su/IntGreaterThanZeroPlumatic
+                (is (schema= [(s/one {:id                   su/IntGreaterThanZero
                                       :group_id             (s/eq (u/the-id &group))
                                       :table_id             (s/eq (mt/id :venues))
                                       :card_id              (s/eq nil)
@@ -101,7 +101,7 @@
                            :group_id (u/the-id &group)
                            :table_id (mt/id :venues)))))
                 (testing "GTAP for same group, other database should not be affected"
-                  (is (schema= [(s/one {:id                   su/IntGreaterThanZeroPlumatic
+                  (is (schema= [(s/one {:id                   su/IntGreaterThanZero
                                         :group_id             (s/eq (u/the-id &group))
                                         :table_id             (s/eq (u/the-id db-2-table))
                                         :card_id              (s/eq nil)
@@ -111,7 +111,7 @@
                                  :group_id (u/the-id &group)
                                  :table_id (u/the-id db-2-table)))))
                 (testing "GTAP for same table, other group should not be affected"
-                  (is (schema= [(s/one {:id                   su/IntGreaterThanZeroPlumatic
+                  (is (schema= [(s/one {:id                   su/IntGreaterThanZero
                                         :group_id             (s/eq (u/the-id other-group))
                                         :table_id             (s/eq (mt/id :venues))
                                         :card_id              (s/eq nil)
diff --git a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj
index c41ae91277e141d9f83333f2d10727e33f05bcf2..8c16b2e2dbe269c562d92f6ed875c3dd5aa8655e 100644
--- a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj
+++ b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj
@@ -110,8 +110,8 @@
   ([{{:keys [project-id]} :details, :as database} dataset-id table-id]
    (get-table (database->client database) project-id dataset-id table-id))
 
-  ([client :- BigQuery, project-id :- (s/maybe su/NonBlankStringPlumatic), dataset-id :- su/NonBlankStringPlumatic,
-    table-id :- su/NonBlankStringPlumatic]
+  ([client :- BigQuery, project-id :- (s/maybe su/NonBlankString), dataset-id :- su/NonBlankString,
+    table-id :- su/NonBlankString]
    (if project-id
      (.getTable client (TableId/of project-id dataset-id table-id) empty-table-options)
      (.getTable client dataset-id table-id empty-table-options))))
diff --git a/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj b/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj
index 03770cec68644dab9e207bdf8e6b98b960988d26..1fc6af52e4746fb1cad69faa1d273f133f7f52ac 100644
--- a/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj
+++ b/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj
@@ -119,13 +119,13 @@
 (def ^:private ValidFieldName #"^[A-Za-z_]\w{0,127}$")
 
 (s/defn ^:private delete-table!
-  [dataset-id :- su/NonBlankStringPlumatic, table-id :- su/NonBlankStringPlumatic]
+  [dataset-id :- su/NonBlankString, table-id :- su/NonBlankString]
   (.delete (bigquery) (TableId/of dataset-id table-id))
   (println (u/format-color 'red "Deleted table `%s.%s.%s`" (project-id) dataset-id table-id)))
 
 (s/defn ^:private create-table!
-  [^String dataset-id :- su/NonBlankStringPlumatic
-   table-id           :- su/NonBlankStringPlumatic
+  [^String dataset-id :- su/NonBlankString
+   table-id           :- su/NonBlankString
    field-name->type   :- {ValidFieldName (apply s/enum valid-field-types)}]
   (u/ignore-exceptions
    (delete-table! dataset-id table-id))
diff --git a/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj b/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj
index 9a8d040441b6211a9ae07562820f15076ab82c83..d175c7e729b8f61a8a23a06479dc8173a44a8653 100644
--- a/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj
+++ b/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj
@@ -367,7 +367,7 @@
 
 ;;; ------------------------------------------- filter (built-in segments) -------------------------------------------
 
-(s/defn ^:private built-in-segment :- (s/maybe su/NonBlankStringPlumatic)
+(s/defn ^:private built-in-segment :- (s/maybe su/NonBlankString)
   [{filter-clause :filter}]
   (let [segments (mbql.u/match filter-clause [:segment (segment-name :guard mbql.u/ga-id?)] segment-name)]
     (when (> (count segments) 1)
diff --git a/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj b/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj
index dfd74196994f48b6ddf7ae9830e85be5238b16ff..e3e2bf3dddf9c69f17d5ae1b44f7b5f9b43a90fb 100644
--- a/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj
+++ b/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj
@@ -37,22 +37,22 @@
 ;; this is just a very limited schema to make sure we're generating valid queries. We should expand it more in the
 ;; future
 
-(def ^:private $ProjectStage   {(s/eq $project)    {su/NonBlankStringPlumatic s/Any}})
-(def ^:private $SortStage      {(s/eq $sort)       {su/NonBlankStringPlumatic (s/enum -1 1)}})
-(def ^:private $MatchStage     {(s/eq $match)      {(s/constrained (s/cond-pre su/NonBlankStringPlumatic s/Keyword)
+(def ^:private $ProjectStage   {(s/eq $project)    {su/NonBlankString s/Any}})
+(def ^:private $SortStage      {(s/eq $sort)       {su/NonBlankString (s/enum -1 1)}})
+(def ^:private $MatchStage     {(s/eq $match)      {(s/constrained (s/cond-pre su/NonBlankString s/Keyword)
                                                                    #(not (#{:$not "$not"} %)))
                                                     s/Any}})
-(def ^:private $GroupStage     {(s/eq $group)      {su/NonBlankStringPlumatic s/Any}})
-(def ^:private $AddFieldsStage {(s/eq :$addFields) {su/NonBlankStringPlumatic s/Any}})
-(def ^:private $LimitStage     {(s/eq $limit)      su/IntGreaterThanZeroPlumatic})
-(def ^:private $SkipStage      {(s/eq $skip)       su/IntGreaterThanZeroPlumatic})
+(def ^:private $GroupStage     {(s/eq $group)      {su/NonBlankString s/Any}})
+(def ^:private $AddFieldsStage {(s/eq :$addFields) {su/NonBlankString s/Any}})
+(def ^:private $LimitStage     {(s/eq $limit)      su/IntGreaterThanZero})
+(def ^:private $SkipStage      {(s/eq $skip)       su/IntGreaterThanZero})
 
 (defn- is-stage? [stage]
   (fn [m] (= (first (keys m)) stage)))
 
 (def ^:private Stage
   (s/both
-   (s/constrained su/MapPlumatic #(= (count (keys %)) 1) "map with a single key")
+   (s/constrained su/Map #(= (count (keys %)) 1) "map with a single key")
    (s/conditional
     (is-stage? $project)    $ProjectStage
     (is-stage? $sort)       $SortStage
@@ -817,7 +817,7 @@
     (recur arg)
     ag))
 
-(s/defn ^:private breakouts-and-ags->projected-fields :- [(s/pair su/NonBlankStringPlumatic "projected-field-name"
+(s/defn ^:private breakouts-and-ags->projected-fields :- [(s/pair su/NonBlankString "projected-field-name"
                                                                   s/Any             "source")]
   "Determine field projections for MBQL breakouts and aggregations. Returns a sequence of pairs like
   `[projected-field-name source]`."
diff --git a/modules/drivers/presto/src/metabase/driver/presto.clj b/modules/drivers/presto/src/metabase/driver/presto.clj
index 0025abac69a8f6113b07f83cc2d4d956201cb1b7..7d462473bdbff292606307dc54ea13749befb0ec 100644
--- a/modules/drivers/presto/src/metabase/driver/presto.clj
+++ b/modules/drivers/presto/src/metabase/driver/presto.clj
@@ -37,9 +37,9 @@
 ;;; Presto API helpers
 
 (def ^:private PrestoConnectionDetails
-  {:host    su/NonBlankStringPlumatic
-   :port    (s/cond-pre su/NonBlankStringPlumatic su/IntGreaterThanZeroPlumatic)
-   :catalog su/NonBlankStringPlumatic
+  {:host    su/NonBlankString
+   :port    (s/cond-pre su/NonBlankString su/IntGreaterThanZero)
+   :catalog su/NonBlankString
    s/Any    s/Any})
 
 (s/defn ^:private details->uri
@@ -196,7 +196,7 @@
                                 (sql.u/quote-name driver :database catalog)))]
     (= v "information_schema")))
 
-(s/defn ^:private database->all-schemas :- #{su/NonBlankStringPlumatic}
+(s/defn ^:private database->all-schemas :- #{su/NonBlankString}
   "Return a set of all schema names in this `database`."
   [driver {{:keys [catalog] :as details} :details :as _database}]
   (let [sql            (presto-common/describe-catalog-sql driver catalog)
diff --git a/src/metabase/api/alert.clj b/src/metabase/api/alert.clj
index 22a2d270ca963b86f5b7f81c25e30fa93127ec1a..fbf1f94403a7580fbdaa8a18b86ceaef8cb3b8a3 100644
--- a/src/metabase/api/alert.clj
+++ b/src/metabase/api/alert.clj
@@ -30,8 +30,8 @@
 (api/defendpoint-schema GET "/"
   "Fetch all alerts"
   [archived user_id]
-  {archived (s/maybe su/BooleanStringPlumatic)
-   user_id  (s/maybe su/IntGreaterThanZeroPlumatic)}
+  {archived (s/maybe su/BooleanString)
+   user_id  (s/maybe su/IntGreaterThanZero)}
   (as-> (pulse/retrieve-alerts {:archived? (Boolean/parseBoolean archived)
                                 :user-id   user_id}) <>
     (filter mi/can-read? <>)
@@ -48,8 +48,8 @@
 (api/defendpoint-schema GET "/question/:id"
   "Fetch all questions for the given question (`Card`) id"
   [id archived]
-  {id       (s/maybe su/IntGreaterThanZeroPlumatic)
-   archived (s/maybe su/BooleanStringPlumatic)}
+  {id       (s/maybe su/IntGreaterThanZero)
+   archived (s/maybe su/BooleanString)}
   (-> (if api/*is-superuser?*
         (pulse/retrieve-alerts-for-cards {:card-ids [id], :archived? (Boolean/parseBoolean archived)})
         (pulse/retrieve-user-alerts-for-card {:card-id id, :user-id api/*current-user-id*, :archived? (Boolean/parseBoolean archived)}))
@@ -140,7 +140,7 @@
    alert_first_only s/Bool
    alert_above_goal (s/maybe s/Bool)
    card             pulse/CardRef
-   channels         (su/non-empty [su/MapPlumatic])}
+   channels         (su/non-empty [su/Map])}
   (validation/check-has-application-permission :subscription false)
   ;; To create an Alert you need read perms for its Card
   (api/read-check Card (u/the-id card))
@@ -170,7 +170,7 @@
    alert_first_only (s/maybe s/Bool)
    alert_above_goal (s/maybe s/Bool)
    card             (s/maybe pulse/CardRef)
-   channels         (s/maybe (su/non-empty [su/MapPlumatic]))
+   channels         (s/maybe (su/non-empty [su/Map]))
    archived         (s/maybe s/Bool)}
   (try
    (validation/check-has-application-permission :monitoring)
diff --git a/src/metabase/api/bookmark.clj b/src/metabase/api/bookmark.clj
index 5c7e0df8f457fff1d119a2e3f003dc6cb577f07c..392597826f4b6a1560b4722c583a4cbeae0a60fb 100644
--- a/src/metabase/api/bookmark.clj
+++ b/src/metabase/api/bookmark.clj
@@ -24,7 +24,7 @@
 (def BookmarkOrderings
   "Schema for an ordered of boomark orderings"
   [{:type Models
-    :item_id su/IntGreaterThanZeroPlumatic}])
+    :item_id su/IntGreaterThanZero}])
 
 (def ^:private lookup
   "Lookup map from model as a string to [model bookmark-model item-id-key]."
@@ -45,7 +45,7 @@
   "Create a new bookmark for user."
   [model id]
   {model Models
-   id    su/IntGreaterThanZeroPlumatic}
+   id    su/IntGreaterThanZero}
   (let [[item-model bookmark-model item-key] (lookup model)]
     (api/read-check item-model id)
     (api/check (not (db/exists? bookmark-model item-key id
@@ -58,7 +58,7 @@
   "Delete a bookmark. Will delete a bookmark assigned to the user making the request by model and id."
   [model id]
   {model Models
-   id    su/IntGreaterThanZeroPlumatic}
+   id    su/IntGreaterThanZero}
   ;; todo: allow admins to include an optional user id to delete for so they can delete other's bookmarks.
   (let [[_ bookmark-model item-key] (lookup model)]
     (db/delete! bookmark-model
diff --git a/src/metabase/api/card.clj b/src/metabase/api/card.clj
index 3ef8b75da9c8b856238007e28562c769cd5105d4..f693af6cf7be6ae1d536595cb954d3927287827f 100644
--- a/src/metabase/api/card.clj
+++ b/src/metabase/api/card.clj
@@ -93,7 +93,7 @@
 (s/defn ^:private cards-with-ids :- (s/maybe [CardInstance])
   "Return unarchived Cards with `card-ids`.
   Make sure cards are returned in the same order as `card-ids`; `[in card-ids]` won't preserve the order."
-  [card-ids :- [su/IntGreaterThanZeroPlumatic]]
+  [card-ids :- [su/IntGreaterThanZero]]
   (when (seq card-ids)
     (let [card-id->card (m/index-by :id (db/select Card, :id [:in (set card-ids)], :archived false))]
       (filter identity (map card-id->card card-ids)))))
@@ -156,7 +156,7 @@
   option. :card_index:"
   [f model_id]
   {f        (s/maybe CardFilterOption)
-   model_id (s/maybe su/IntGreaterThanZeroPlumatic)}
+   model_id (s/maybe su/IntGreaterThanZero)}
   (let [f (keyword f)]
     (when (contains? #{:database :table :using_model} f)
       (api/checkp (integer? model_id) "model_id" (format "model_id is a required parameter when filter mode is '%s'"
@@ -201,8 +201,8 @@
   "Get the timelines for card with ID. Looks up the collection the card is in and uses that."
   [id include start end]
   {include (s/maybe api.timeline/Include)
-   start   (s/maybe su/TemporalStringPlumatic)
-   end     (s/maybe su/TemporalStringPlumatic)}
+   start   (s/maybe su/TemporalString)
+   end     (s/maybe su/TemporalString)}
   (let [{:keys [collection_id] :as _card} (api/read-check Card id)]
     ;; subtlety here. timeline access is based on the collection at the moment so this check should be identical. If
     ;; we allow adding more timelines to a card in the future, we will need to filter on read-check and i don't think
@@ -377,17 +377,17 @@ saved later when it is ready."
   "Create a new `Card`."
   [:as {{:keys [collection_id collection_position dataset_query description display name
                 parameters parameter_mappings result_metadata visualization_settings cache_ttl], :as body} :body}]
-  {name                   su/NonBlankStringPlumatic
-   dataset_query          su/MapPlumatic
-   parameters             (s/maybe [su/ParameterPlumatic])
-   parameter_mappings     (s/maybe [su/ParameterMappingPlumatic])
-   description            (s/maybe su/NonBlankStringPlumatic)
-   display                su/NonBlankStringPlumatic
-   visualization_settings su/MapPlumatic
-   collection_id          (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_position    (s/maybe su/IntGreaterThanZeroPlumatic)
+  {name                   su/NonBlankString
+   dataset_query          su/Map
+   parameters             (s/maybe [su/Parameter])
+   parameter_mappings     (s/maybe [su/ParameterMapping])
+   description            (s/maybe su/NonBlankString)
+   display                su/NonBlankString
+   visualization_settings su/Map
+   collection_id          (s/maybe su/IntGreaterThanZero)
+   collection_position    (s/maybe su/IntGreaterThanZero)
    result_metadata        (s/maybe qr/ResultsMetadata)
-   cache_ttl              (s/maybe su/IntGreaterThanZeroPlumatic)}
+   cache_ttl              (s/maybe su/IntGreaterThanZero)}
   ;; check that we have permissions to run the query that we're trying to save
   (check-data-permissions-for-query dataset_query)
   ;; check that we have permissions for the collection we're trying to save this card to, if applicable
@@ -398,7 +398,7 @@ saved later when it is ready."
 (api/defendpoint-schema POST "/:id/copy"
   "Copy a `Card`, with the new name 'Copy of _name_'"
   [id]
-  {id (s/maybe su/IntGreaterThanZeroPlumatic)}
+  {id (s/maybe su/IntGreaterThanZero)}
   (let [orig-card (api/read-check Card id)
         new-name  (str (trs "Copy of ") (:name orig-card))
         new-card  (assoc orig-card :name new-name)]
@@ -607,20 +607,20 @@ saved later when it is ready."
                    collection_position enable_embedding embedding_params result_metadata parameters
                    cache_ttl dataset collection_preview]
             :as   card-updates} :body}]
-  {name                   (s/maybe su/NonBlankStringPlumatic)
-   parameters             (s/maybe [su/ParameterPlumatic])
-   dataset_query          (s/maybe su/MapPlumatic)
+  {name                   (s/maybe su/NonBlankString)
+   parameters             (s/maybe [su/Parameter])
+   dataset_query          (s/maybe su/Map)
    dataset                (s/maybe s/Bool)
-   display                (s/maybe su/NonBlankStringPlumatic)
+   display                (s/maybe su/NonBlankString)
    description            (s/maybe s/Str)
-   visualization_settings (s/maybe su/MapPlumatic)
+   visualization_settings (s/maybe su/Map)
    archived               (s/maybe s/Bool)
    enable_embedding       (s/maybe s/Bool)
-   embedding_params       (s/maybe su/EmbeddingParamsPlumatic)
-   collection_id          (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_position    (s/maybe su/IntGreaterThanZeroPlumatic)
+   embedding_params       (s/maybe su/EmbeddingParams)
+   collection_id          (s/maybe su/IntGreaterThanZero)
+   collection_position    (s/maybe su/IntGreaterThanZero)
    result_metadata        (s/maybe qr/ResultsMetadata)
-   cache_ttl              (s/maybe su/IntGreaterThanZeroPlumatic)
+   cache_ttl              (s/maybe su/IntGreaterThanZero)
    collection_preview     (s/maybe s/Bool)}
   (let [card-before-update (hydrate (api/write-check Card id)
                                     [:moderation_reviews :moderator_details])]
@@ -739,7 +739,7 @@ saved later when it is ready."
   "Bulk update endpoint for Card Collections. Move a set of `Cards` with CARD_IDS into a `Collection` with
   COLLECTION_ID, or remove them from any Collections by passing a `null` COLLECTION_ID."
   [:as {{:keys [card_ids collection_id]} :body}]
-  {card_ids [su/IntGreaterThanZeroPlumatic], collection_id (s/maybe su/IntGreaterThanZeroPlumatic)}
+  {card_ids [su/IntGreaterThanZero], collection_id (s/maybe su/IntGreaterThanZero)}
   (move-cards-to-collection! collection_id card_ids)
   {:status :ok})
 
@@ -753,7 +753,7 @@ saved later when it is ready."
   [card-id :as {{:keys [parameters ignore_cache dashboard_id collection_preview], :or {ignore_cache false dashboard_id nil}} :body}]
   {ignore_cache (s/maybe s/Bool)
    collection_preview (s/maybe s/Bool)
-   dashboard_id (s/maybe su/IntGreaterThanZeroPlumatic)}
+   dashboard_id (s/maybe su/IntGreaterThanZero)}
   ;; TODO -- we should probably warn if you pass `dashboard_id`, and tell you to use the new
   ;;
   ;;    POST /api/dashboard/:dashboard-id/card/:card-id/query
@@ -774,7 +774,7 @@ saved later when it is ready."
   `parameters` should be passed as query parameter encoded as a serialized JSON string (this is because this endpoint
   is normally used to power 'Download Results' buttons that use HTML `form` actions)."
   [card-id export-format :as {{:keys [parameters]} :params}]
-  {parameters    (s/maybe su/JSONStringPlumatic)
+  {parameters    (s/maybe su/JSONString)
    export-format api.dataset/ExportFormat}
   (qp.card/run-query-for-card-async
    card-id export-format
@@ -862,7 +862,7 @@ saved later when it is ready."
   "Mark the model (card) as persisted. Runs the query and saves it to the database backing the card and hot swaps this
   query in place of the model's query."
   [card-id]
-  {card-id su/IntGreaterThanZeroPlumatic}
+  {card-id su/IntGreaterThanZero}
   (api/let-404 [{:keys [dataset database_id] :as card} (db/select-one Card :id card-id)]
     (let [database (db/select-one Database :id database_id)]
       (api/write-check database)
@@ -886,7 +886,7 @@ saved later when it is ready."
 (api/defendpoint-schema POST "/:card-id/refresh"
   "Refresh the persisted model caching `card-id`."
   [card-id]
-  {card-id su/IntGreaterThanZeroPlumatic}
+  {card-id su/IntGreaterThanZero}
   (api/let-404 [card           (db/select-one Card :id card-id)
                 persisted-info (db/select-one PersistedInfo :card_id card-id)]
     (when (not (:dataset card))
@@ -902,7 +902,7 @@ saved later when it is ready."
   "Unpersist this model. Deletes the persisted table backing the model and all queries after this will use the card's
   query rather than the saved version of the query."
   [card-id]
-  {card-id su/IntGreaterThanZeroPlumatic}
+  {card-id su/IntGreaterThanZero}
   (api/let-404 [_card (db/select-one Card :id card-id)]
     (api/let-404 [persisted-info (db/select-one PersistedInfo :card_id card-id)]
       (api/write-check (db/select-one Database :id (:database_id persisted-info)))
diff --git a/src/metabase/api/collection.clj b/src/metabase/api/collection.clj
index 22486f2793be4a1e27fa71a66acfa9d9c0bb4ce4..1375ce790b3e5fde38867742165ef85c849fa3e7 100644
--- a/src/metabase/api/collection.clj
+++ b/src/metabase/api/collection.clj
@@ -51,8 +51,8 @@
   By default, this returns non-archived Collections, but instead you can show archived ones by passing
   `?archived=true`."
   [archived namespace]
-  {archived  (s/maybe su/BooleanStringPlumatic)
-   namespace (s/maybe su/NonBlankStringPlumatic)}
+  {archived  (s/maybe su/BooleanString)
+   namespace (s/maybe su/NonBlankString)}
   (let [archived? (Boolean/parseBoolean archived)]
     (as-> (db/select Collection
             {:where    [:and
@@ -100,8 +100,8 @@
   The here and below keys indicate the types of items at this particular level of the tree (here) and in its
   subtree (below)."
   [exclude-archived namespace]
-  {exclude-archived (s/maybe su/BooleanStringPlumatic)
-   namespace        (s/maybe su/NonBlankStringPlumatic)}
+  {exclude-archived (s/maybe su/BooleanString)
+   namespace        (s/maybe su/NonBlankString)}
   (let [coll-type-ids (reduce (fn [acc {:keys [collection_id dataset] :as _x}]
                                 (update acc (if dataset :dataset :card) conj collection_id))
                               {:dataset #{}
@@ -628,7 +628,7 @@
   "Fetch the root Collection's timelines."
   [include archived]
   {include  (s/maybe api.timeline/Include)
-   archived (s/maybe su/BooleanStringPlumatic)}
+   archived (s/maybe su/BooleanString)}
   (let [archived? (Boolean/parseBoolean archived)]
     (timeline/timelines-for-collection nil {:timeline/events?   (= include "events")
                                             :timeline/archived? archived?})))
@@ -638,7 +638,7 @@
   "Fetch a specific Collection's timelines."
   [id include archived]
   {include  (s/maybe api.timeline/Include)
-   archived (s/maybe su/BooleanStringPlumatic)}
+   archived (s/maybe su/BooleanString)}
   (let [archived? (Boolean/parseBoolean archived)]
     (timeline/timelines-for-collection id {:timeline/events?   (= include "events")
                                            :timeline/archived? archived?})))
@@ -654,7 +654,7 @@
                    when `all`, return everything. By default returns everything"
   [id models archived pinned_state sort_column sort_direction]
   {models         (s/maybe models-schema)
-   archived       (s/maybe su/BooleanStringPlumatic)
+   archived       (s/maybe su/BooleanString)
    pinned_state   (s/maybe (apply s/enum valid-pinned-state-values))
    sort_column    (s/maybe (apply s/enum valid-sort-columns))
    sort_direction (s/maybe (apply s/enum valid-sort-directions))}
@@ -676,7 +676,7 @@
 (api/defendpoint-schema GET "/root"
   "Return the 'Root' Collection object with standard details added"
   [namespace]
-  {namespace (s/maybe su/NonBlankStringPlumatic)}
+  {namespace (s/maybe su/NonBlankString)}
   (-> (root-collection namespace)
       (api/read-check)
       (dissoc ::collection.root/is-root?)))
@@ -710,8 +710,8 @@
   `snippets`, you can pass the `?namespace=` parameter."
   [models archived namespace pinned_state sort_column sort_direction]
   {models         (s/maybe models-schema)
-   archived       (s/maybe su/BooleanStringPlumatic)
-   namespace      (s/maybe su/NonBlankStringPlumatic)
+   archived       (s/maybe su/BooleanString)
+   namespace      (s/maybe su/NonBlankString)
    pinned_state   (s/maybe (apply s/enum valid-pinned-state-values))
    sort_column    (s/maybe (apply s/enum valid-sort-columns))
    sort_direction (s/maybe (apply s/enum valid-sort-directions))}
@@ -762,11 +762,11 @@
 (api/defendpoint-schema POST "/"
   "Create a new Collection."
   [:as {{:keys [name color description parent_id namespace authority_level] :as body} :body}]
-  {name            su/NonBlankStringPlumatic
+  {name            su/NonBlankString
    color           collection/hex-color-regex
-   description     (s/maybe su/NonBlankStringPlumatic)
-   parent_id       (s/maybe su/IntGreaterThanZeroPlumatic)
-   namespace       (s/maybe su/NonBlankStringPlumatic)
+   description     (s/maybe su/NonBlankString)
+   parent_id       (s/maybe su/IntGreaterThanZero)
+   namespace       (s/maybe su/NonBlankString)
    authority_level collection/AuthorityLevel}
   (create-collection! body))
 
@@ -821,11 +821,11 @@
 (api/defendpoint-schema PUT "/:id"
   "Modify an existing Collection, including archiving or unarchiving it, or moving it."
   [id, :as {{:keys [name color description archived parent_id authority_level], :as collection-updates} :body}]
-  {name                                   (s/maybe su/NonBlankStringPlumatic)
+  {name                                   (s/maybe su/NonBlankString)
    color                                  (s/maybe collection/hex-color-regex)
-   description                            (s/maybe su/NonBlankStringPlumatic)
+   description                            (s/maybe su/NonBlankString)
    archived                               (s/maybe s/Bool)
-   parent_id                              (s/maybe su/IntGreaterThanZeroPlumatic)
+   parent_id                              (s/maybe su/IntGreaterThanZero)
    authority_level                        collection/AuthorityLevel}
   ;; do we have perms to edit this Collection?
   (let [collection-before-update (api/write-check Collection id)]
@@ -857,7 +857,7 @@
 (api/defendpoint-schema GET "/graph"
   "Fetch a graph of all Collection Permissions."
   [namespace]
-  {namespace (s/maybe su/NonBlankStringPlumatic)}
+  {namespace (s/maybe su/NonBlankString)}
   (api/check-superuser)
   (graph/graph namespace))
 
@@ -900,8 +900,8 @@
   "Do a batch update of Collections Permissions by passing in a modified graph.
   Will overwrite parts of the graph that are present in the request, and leave the rest unchanged."
   [:as {{:keys [namespace], :as body} :body}]
-  {body      su/MapPlumatic
-   namespace (s/maybe su/NonBlankStringPlumatic)}
+  {body      su/Map
+   namespace (s/maybe su/NonBlankString)}
   (api/check-superuser)
   (->> (dissoc body :namespace)
        decode-graph
diff --git a/src/metabase/api/common.clj b/src/metabase/api/common.clj
index b448ea34935b04d528b22004dabd46ae72023e5b..5f16e2032fd752b1676dd46663a1f8f29920db01 100644
--- a/src/metabase/api/common.clj
+++ b/src/metabase/api/common.clj
@@ -485,7 +485,7 @@
     (api/column-will-change? :archived (db/select-one Collection :id 10) {:archived false}) ; -> false, because value did not change
 
     (api/column-will-change? :archived (db/select-one Collection :id 10) {}) ; -> false; value not specified in updates (request body)"
-  [k :- schema/Keyword, object-before-updates :- su/MapPlumatic, object-updates :- su/MapPlumatic]
+  [k :- schema/Keyword, object-before-updates :- su/Map, object-updates :- su/Map]
   (boolean
    (and (contains? object-updates k)
         (not= (get object-before-updates k)
@@ -496,9 +496,9 @@
 (schema/defn reconcile-position-for-collection!
   "Compare `old-position` and `new-position` to determine what needs to be updated based on the position change. Used
   for fixing card/dashboard/pulse changes that impact other instances in the collection"
-  [collection-id :- (schema/maybe su/IntGreaterThanZeroPlumatic)
-   old-position  :- (schema/maybe su/IntGreaterThanZeroPlumatic)
-   new-position  :- (schema/maybe su/IntGreaterThanZeroPlumatic)]
+  [collection-id :- (schema/maybe su/IntGreaterThanZero)
+   old-position  :- (schema/maybe su/IntGreaterThanZero)
+   new-position  :- (schema/maybe su/IntGreaterThanZero)]
   (let [update-fn! (fn [plus-or-minus position-update-clause]
                      (doseq [model '[Card Dashboard Pulse]]
                        (db/update-where! model {:collection_id       collection-id
@@ -521,15 +521,15 @@
 
 (def ^:private ModelWithPosition
   "Intended to cover Cards/Dashboards/Pulses, it only asserts collection id and position, allowing extra keys"
-  {:collection_id       (schema/maybe su/IntGreaterThanZeroPlumatic)
-   :collection_position (schema/maybe su/IntGreaterThanZeroPlumatic)
+  {:collection_id       (schema/maybe su/IntGreaterThanZero)
+   :collection_position (schema/maybe su/IntGreaterThanZero)
    schema/Any           schema/Any})
 
 (def ^:private ModelWithOptionalPosition
   "Intended to cover Cards/Dashboards/Pulses updates. Collection id and position are optional, if they are not
   present, they didn't change. If they are present, they might have changed and we need to compare."
-  {(schema/optional-key :collection_id)       (schema/maybe su/IntGreaterThanZeroPlumatic)
-   (schema/optional-key :collection_position) (schema/maybe su/IntGreaterThanZeroPlumatic)
+  {(schema/optional-key :collection_id)       (schema/maybe su/IntGreaterThanZero)
+   (schema/optional-key :collection_position) (schema/maybe su/IntGreaterThanZero)
    schema/Any                                 schema/Any})
 
 (schema/defn maybe-reconcile-collection-position!
diff --git a/src/metabase/api/dashboard.clj b/src/metabase/api/dashboard.clj
index 9c44a57aea5a704a7943c42b43c0251d00ec1967..defb929f79c93e111dd2a72484461f810a65fc1d 100644
--- a/src/metabase/api/dashboard.clj
+++ b/src/metabase/api/dashboard.clj
@@ -79,12 +79,12 @@
 (api/defendpoint-schema POST "/"
   "Create a new Dashboard."
   [:as {{:keys [name description parameters cache_ttl collection_id collection_position], :as _dashboard} :body}]
-  {name                su/NonBlankStringPlumatic
-   parameters          (s/maybe [su/ParameterPlumatic])
+  {name                su/NonBlankString
+   parameters          (s/maybe [su/Parameter])
    description         (s/maybe s/Str)
-   cache_ttl           (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_id       (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_position (s/maybe su/IntGreaterThanZeroPlumatic)}
+   cache_ttl           (s/maybe su/IntGreaterThanZero)
+   collection_id       (s/maybe su/IntGreaterThanZero)
+   collection_position (s/maybe su/IntGreaterThanZero)}
   ;; if we're trying to save the new dashboard in a Collection make sure we have permissions to do that
   (collection/check-write-perms-for-collection collection_id)
   (let [dashboard-data {:name                name
@@ -318,10 +318,10 @@
   "Copy a Dashboard."
   [from-dashboard-id :as {{:keys [name description collection_id collection_position
                                   is_deep_copy], :as _dashboard} :body}]
-  {name                   (s/maybe su/NonBlankStringPlumatic)
+  {name                   (s/maybe su/NonBlankString)
    description            (s/maybe s/Str)
-   collection_id          (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_position    (s/maybe su/IntGreaterThanZeroPlumatic)
+   collection_id          (s/maybe su/IntGreaterThanZero)
+   collection_position    (s/maybe su/IntGreaterThanZero)
    is_deep_copy           (s/maybe s/Bool)}
   ;; if we're trying to save the new dashboard in a Collection make sure we have permissions to do that
   (collection/check-write-perms-for-collection collection_id)
@@ -388,19 +388,19 @@
   [id :as {{:keys [description name parameters caveats points_of_interest show_in_getting_started enable_embedding
                    embedding_params position archived collection_id collection_position cache_ttl]
             :as dash-updates} :body}]
-  {name                    (s/maybe su/NonBlankStringPlumatic)
+  {name                    (s/maybe su/NonBlankString)
    description             (s/maybe s/Str)
    caveats                 (s/maybe s/Str)
    points_of_interest      (s/maybe s/Str)
    show_in_getting_started (s/maybe s/Bool)
    enable_embedding        (s/maybe s/Bool)
-   embedding_params        (s/maybe su/EmbeddingParamsPlumatic)
-   parameters              (s/maybe [su/ParameterPlumatic])
-   position                (s/maybe su/IntGreaterThanZeroPlumatic)
+   embedding_params        (s/maybe su/EmbeddingParams)
+   parameters              (s/maybe [su/Parameter])
+   position                (s/maybe su/IntGreaterThanZero)
    archived                (s/maybe s/Bool)
-   collection_id           (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_position     (s/maybe su/IntGreaterThanZeroPlumatic)
-   cache_ttl               (s/maybe su/IntGreaterThanZeroPlumatic)}
+   collection_id           (s/maybe su/IntGreaterThanZero)
+   collection_position     (s/maybe su/IntGreaterThanZero)
+   cache_ttl               (s/maybe su/IntGreaterThanZero)}
   (let [dash-before-update (api/write-check Dashboard id)]
     ;; Do various permissions checks as needed
     (collection/check-allowed-to-change-collection dash-before-update dash-updates)
@@ -486,7 +486,7 @@
 (api/defendpoint-schema POST "/:id/cards"
   "Add a `Card` to a Dashboard."
   [id :as {{:keys [cardId parameter_mappings], :as dashboard-card} :body}]
-  {cardId             (s/maybe su/IntGreaterThanZeroPlumatic)
+  {cardId             (s/maybe su/IntGreaterThanZero)
    parameter_mappings (s/maybe [dashboard-card/ParamMapping])}
   (api/check-not-archived (api/write-check Dashboard id))
   (when cardId
@@ -536,16 +536,16 @@
 
 (def ^:private UpdatedDashboardCard
   (su/with-api-error-message
-    {:id                                  (su/with-api-error-message su/IntGreaterThanOrEqualToZeroPlumatic
+    {:id                                  (su/with-api-error-message su/IntGreaterThanOrEqualToZero
                                             "value must be a DashboardCard ID.")
-     (s/optional-key :size_x)             (s/maybe su/IntGreaterThanZeroPlumatic)
-     (s/optional-key :size_y)             (s/maybe su/IntGreaterThanZeroPlumatic)
-     (s/optional-key :row)                (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)
-     (s/optional-key :col)                (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)
-     (s/optional-key :parameter_mappings) (s/maybe [{:parameter_id su/NonBlankStringPlumatic
+     (s/optional-key :size_x)             (s/maybe su/IntGreaterThanZero)
+     (s/optional-key :size_y)             (s/maybe su/IntGreaterThanZero)
+     (s/optional-key :row)                (s/maybe su/IntGreaterThanOrEqualToZero)
+     (s/optional-key :col)                (s/maybe su/IntGreaterThanOrEqualToZero)
+     (s/optional-key :parameter_mappings) (s/maybe [{:parameter_id su/NonBlankString
                                                      :target       s/Any
                                                      s/Keyword     s/Any}])
-     (s/optional-key :series)             (s/maybe [su/MapPlumatic])
+     (s/optional-key :series)             (s/maybe [su/Map])
      s/Keyword                            s/Any}
     "value must be a valid DashboardCard map."))
 
@@ -575,7 +575,7 @@
 (api/defendpoint-schema DELETE "/:id/cards"
   "Remove a `DashboardCard` from a Dashboard."
   [id dashcardId]
-  {dashcardId su/IntStringGreaterThanZeroPlumatic}
+  {dashcardId su/IntStringGreaterThanZero}
   (api/check-not-archived (api/write-check Dashboard id))
   (when-let [dashboard-card (db/select-one DashboardCard :id (Integer/parseInt dashcardId))]
     (api/check-500 (dashboard-card/delete-dashboard-card! dashboard-card api/*current-user-id*))
@@ -592,7 +592,7 @@
 (api/defendpoint-schema POST "/:id/revert"
   "Revert a Dashboard to a prior `Revision`."
   [id :as {{:keys [revision_id]} :body}]
-  {revision_id su/IntGreaterThanZeroPlumatic}
+  {revision_id su/IntGreaterThanZero}
   (api/write-check Dashboard id)
   (revision/revert!
     :entity      Dashboard
@@ -681,7 +681,7 @@
   "How many results to return when chain filtering"
   1000)
 
-(s/defn ^:private mappings->field-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic})
+(s/defn ^:private mappings->field-ids :- (s/maybe #{su/IntGreaterThanZero})
   [parameter-mappings :- (s/maybe (s/cond-pre #{dashboard-card/ParamMapping} [dashboard-card/ParamMapping]))]
   (set (for [param parameter-mappings
              :let  [field-clause (params/param-target->field-clause (:target param) (:dashcard param))]
@@ -721,10 +721,10 @@
   ([dashboard param-key constraint-param-key->value]
    (chain-filter dashboard param-key constraint-param-key->value nil))
 
-  ([dashboard                   :- su/MapPlumatic
-    param-key                   :- su/NonBlankStringPlumatic
-    constraint-param-key->value :- su/MapPlumatic
-    query                       :- (s/maybe su/NonBlankStringPlumatic)]
+  ([dashboard                   :- su/Map
+    param-key                   :- su/NonBlankString
+    constraint-param-key->value :- su/Map
+    query                       :- (s/maybe su/NonBlankString)]
    (let [constraints (chain-filter-constraints dashboard constraint-param-key->value)
          field-ids   (param-key->field-ids dashboard param-key)]
      (when (empty? field-ids)
@@ -786,10 +786,10 @@
   ([dashboard param-key query-params]
    (param-values dashboard param-key query-params nil))
 
-  ([dashboard                   :- su/MapPlumatic
-    param-key                   :- su/NonBlankStringPlumatic
-    constraint-param-key->value :- su/MapPlumatic
-    query                       :- (s/maybe su/NonBlankStringPlumatic)]
+  ([dashboard                   :- su/Map
+    param-key                   :- su/NonBlankString
+    constraint-param-key->value :- su/Map
+    query                       :- (s/maybe su/NonBlankString)]
    (let [dashboard (hydrate dashboard :resolved-params)
          param     (get (:resolved-params dashboard) param-key)]
      (when-not param
@@ -849,10 +849,10 @@
 
     `filtered` Field ID -> subset of `filtering` Field IDs that would be used in chain filter query"
   [:as {{:keys [filtered filtering]} :params}]
-  {filtered  (s/cond-pre su/IntStringGreaterThanZeroPlumatic
-                         (su/non-empty [su/IntStringGreaterThanZeroPlumatic]))
-   filtering (s/maybe (s/cond-pre su/IntStringGreaterThanZeroPlumatic
-                                  (su/non-empty [su/IntStringGreaterThanZeroPlumatic])))}
+  {filtered  (s/cond-pre su/IntStringGreaterThanZero
+                         (su/non-empty [su/IntStringGreaterThanZero]))
+   filtering (s/maybe (s/cond-pre su/IntStringGreaterThanZero
+                                  (su/non-empty [su/IntStringGreaterThanZero])))}
     ;; parse IDs for filtered/filtering
   (letfn [(parse-ids [s]
             (set (cond
@@ -868,7 +868,7 @@
 (def ParameterWithID
   "Schema for a parameter map with an string `:id`."
   (su/with-api-error-message
-    {:id       su/NonBlankStringPlumatic
+    {:id       su/NonBlankString
      s/Keyword s/Any}
     "value must be a parameter map with an 'id' key"))
 
@@ -878,9 +878,9 @@
 (api/defendpoint-schema GET "/:dashboard-id/dashcard/:dashcard-id/execute"
   "Fetches the values for filling in execution parameters. Pass PK parameters and values to select."
   [dashboard-id dashcard-id parameters]
-  {dashboard-id su/IntGreaterThanZeroPlumatic
-   dashcard-id su/IntGreaterThanZeroPlumatic
-   parameters su/JSONStringPlumatic}
+  {dashboard-id su/IntGreaterThanZero
+   dashcard-id su/IntGreaterThanZero
+   parameters su/JSONString}
   (api/read-check Dashboard dashboard-id)
   (actions.execution/fetch-values dashboard-id dashcard-id (json/parse-string parameters)))
 
@@ -891,8 +891,8 @@
    `parameters` should be the mapped dashboard parameters with values.
    `extra_parameters` should be the extra, user entered parameter values."
   [dashboard-id dashcard-id :as {{:keys [parameters], :as _body} :body}]
-  {dashboard-id su/IntGreaterThanZeroPlumatic
-   dashcard-id su/IntGreaterThanZeroPlumatic
+  {dashboard-id su/IntGreaterThanZero
+   dashcard-id su/IntGreaterThanZero
    parameters (s/maybe {s/Keyword s/Any})}
   (api/read-check Dashboard dashboard-id)
   ;; Undo middleware string->keyword coercion
@@ -920,7 +920,7 @@
   `parameters` should be passed as query parameter encoded as a serialized JSON string (this is because this endpoint
   is normally used to power 'Download Results' buttons that use HTML `form` actions)."
   [dashboard-id dashcard-id card-id export-format :as {{:keys [parameters], :as request-parameters} :params}]
-  {parameters    (s/maybe su/JSONStringPlumatic)
+  {parameters    (s/maybe su/JSONString)
    export-format api.dataset/ExportFormat}
   (m/mapply qp.dashboard/run-query-for-dashcard-async
             (merge
diff --git a/src/metabase/api/database.clj b/src/metabase/api/database.clj
index 611b7d6b74890d21abc1c3041f5fb2ce587f5147..4223317124f6bb997113635fe87d63f9cfd41164 100644
--- a/src/metabase/api/database.clj
+++ b/src/metabase/api/database.clj
@@ -53,7 +53,7 @@
 (def DBEngineString
   "Schema for a valid database engine name, e.g. `h2` or `postgres`."
   (su/with-api-error-message (s/constrained
-                              su/NonBlankStringPlumatic
+                              su/NonBlankString
                               #(u/ignore-exceptions (driver/the-driver %))
                               "Valid database engine")
     (deferred-tru "value must be a valid database engine.")))
@@ -80,7 +80,7 @@
   permissions; there was a specific option where you could give a Perms Group permissions to run existing Cards with
   native queries, but not to create new ones. With the advent of what is currently being called 'Space-Age
   Permissions', all Cards' permissions are based on their parent Collection, removing the need for native read perms."
-  [dbs :- [su/MapPlumatic]]
+  [dbs :- [su/Map]]
   (for [db dbs]
     (assoc db :native_permissions (if (perms/set-has-full-permissions? @api/*current-user-permissions-set*
                                         (perms/adhoc-native-query-path (u/the-id db)))
@@ -262,12 +262,12 @@
   * `exclude_uneditable_details` will only include DBs for which the current user can edit the DB details. Has no
     effect unless Enterprise Edition code is available and the advanced-permissions feature is enabled."
   [include_tables include_cards include saved include_editable_data_model exclude_uneditable_details]
-  {include_tables                (s/maybe su/BooleanStringPlumatic)
-   include_cards                 (s/maybe su/BooleanStringPlumatic)
+  {include_tables                (s/maybe su/BooleanString)
+   include_cards                 (s/maybe su/BooleanString)
    include                       FetchAllIncludeValues
-   saved                         (s/maybe su/BooleanStringPlumatic)
-   include_editable_data_model   (s/maybe su/BooleanStringPlumatic)
-   exclude_uneditable_details    (s/maybe su/BooleanStringPlumatic)}
+   saved                         (s/maybe su/BooleanString)
+   include_editable_data_model   (s/maybe su/BooleanString)
+   exclude_uneditable_details    (s/maybe su/BooleanString)}
   (when (and config/is-dev?
              (or include_tables include_cards))
     ;; don't need to i18n since this is dev-facing only
@@ -404,8 +404,8 @@
   In addition, if the user has no data access for the DB (aka block permissions), it will return only the DB name, ID
   and tables, with no additional metadata."
   [id include_hidden include_editable_data_model]
-  {include_hidden              (s/maybe su/BooleanStringPlumatic)
-   include_editable_data_model (s/maybe su/BooleanStringPlumatic)}
+  {include_hidden              (s/maybe su/BooleanString)
+   include_editable_data_model (s/maybe su/BooleanString)}
   (db-metadata id
                (Boolean/parseBoolean include_hidden)
                (Boolean/parseBoolean include_editable_data_model)))
@@ -527,8 +527,8 @@
   When Fields lack a semantic_type, they are returned in the format `[field_name \"table_name base_type\"]`"
   [id prefix substring]
   {id        s/Int
-   prefix    (s/maybe su/NonBlankStringPlumatic)
-   substring (s/maybe su/NonBlankStringPlumatic)}
+   prefix    (s/maybe su/NonBlankString)
+   substring (s/maybe su/NonBlankString)}
   (api/read-check Database id)
   (when (and (str/blank? prefix) (str/blank? substring))
     (throw (ex-info "Must include prefix or search" {:status-code 400})))
@@ -548,7 +548,7 @@
   This is intended for use with the ACE Editor when the User is typing in a template tag for a `Card`, e.g. {{#...}}."
   [id query]
   {id    s/Int
-   query su/NonBlankStringPlumatic}
+   query su/NonBlankString}
   (api/read-check Database id)
   (try
     (->> (autocomplete-cards id query)
@@ -640,14 +640,14 @@
                             (:name field)))]
     (contains? driver-props "ssl")))
 
-(s/defn ^:private test-connection-details :- su/MapPlumatic
+(s/defn ^:private test-connection-details :- su/Map
   "Try a making a connection to database `engine` with `details`.
 
   If the `details` has SSL explicitly enabled, go with that and do not accept plaintext connections. If it is disabled,
   try twice: once with SSL, and a second time without if the first fails. If either attempt is successful, returns
   the details used to successfully connect. Otherwise returns a map with the connection error message. (This map will
   also contain the key `:valid` = `false`, which you can use to distinguish an error from valid details.)"
-  [engine :- DBEngineString, details :- su/MapPlumatic]
+  [engine :- DBEngineString, details :- su/Map]
   (let [;; Try SSL first if SSL is supported and not already enabled
         ;; If not successful or not applicable, details-with-ssl will be nil
         details-with-ssl (assoc details :ssl true)
@@ -667,14 +667,14 @@
 (api/defendpoint-schema POST "/"
   "Add a new `Database`."
   [:as {{:keys [name engine details is_full_sync is_on_demand schedules auto_run_queries cache_ttl]} :body}]
-  {name             su/NonBlankStringPlumatic
+  {name             su/NonBlankString
    engine           DBEngineString
-   details          su/MapPlumatic
+   details          su/Map
    is_full_sync     (s/maybe s/Bool)
    is_on_demand     (s/maybe s/Bool)
    schedules        (s/maybe sync.schedules/ExpandedSchedulesMap)
    auto_run_queries (s/maybe s/Bool)
-   cache_ttl        (s/maybe su/IntGreaterThanZeroPlumatic)}
+   cache_ttl        (s/maybe su/IntGreaterThanZero)}
   (api/check-superuser)
   (let [is-full-sync?    (or (nil? is_full_sync)
                              (boolean is_full_sync))
@@ -716,7 +716,7 @@
   ;; TODO - why do we pass the DB in under the key `details`?
   [:as {{{:keys [engine details]} :details} :body}]
   {engine  DBEngineString
-   details su/MapPlumatic}
+   details su/Map}
   (api/check-superuser)
   (let [details-or-error (test-connection-details engine details)]
     {:valid (not (false? (:valid details-or-error)))}))
@@ -752,7 +752,7 @@
 (api/defendpoint-schema POST "/:id/persist"
   "Attempt to enable model persistence for a database. If already enabled returns a generic 204."
   [id]
-  {:id su/IntGreaterThanZeroPlumatic}
+  {:id su/IntGreaterThanZero}
   (api/check (public-settings/persisted-models-enabled)
              400
              (tru "Persisting models is not enabled."))
@@ -779,7 +779,7 @@
 (api/defendpoint-schema POST "/:id/unpersist"
   "Attempt to disable model persistence for a database. If already not enabled, just returns a generic 204."
   [id]
-  {:id su/IntGreaterThanZeroPlumatic}
+  {:id su/IntGreaterThanZero}
   (api/let-404 [database (db/select-one Database :id id)]
     (api/write-check database)
     (if (-> database :options :persist-models-enabled)
@@ -796,17 +796,17 @@
   "Update a `Database`."
   [id :as {{:keys [name engine details is_full_sync is_on_demand description caveats points_of_interest schedules
                    auto_run_queries refingerprint cache_ttl settings]} :body}]
-  {name               (s/maybe su/NonBlankStringPlumatic)
+  {name               (s/maybe su/NonBlankString)
    engine             (s/maybe DBEngineString)
    refingerprint      (s/maybe s/Bool)
-   details            (s/maybe su/MapPlumatic)
+   details            (s/maybe su/Map)
    schedules          (s/maybe sync.schedules/ExpandedSchedulesMap)
    description        (s/maybe s/Str)   ; s/Str instead of su/NonBlankString because we don't care
    caveats            (s/maybe s/Str)   ; whether someone sets these to blank strings
    points_of_interest (s/maybe s/Str)
    auto_run_queries   (s/maybe s/Bool)
-   cache_ttl          (s/maybe su/IntGreaterThanZeroPlumatic)
-   settings           (s/maybe su/MapPlumatic)}
+   cache_ttl          (s/maybe su/IntGreaterThanZero)
+   settings           (s/maybe su/Map)}
   ;; TODO - ensure that custom schedules and let-user-control-scheduling go in lockstep
   (let [existing-database (api/write-check (db/select-one Database :id id))
         details           (driver.u/db-details-client->server engine details)
diff --git a/src/metabase/api/dataset.clj b/src/metabase/api/dataset.clj
index 26aec011a30cc8665369f117c711345aa187b652..bd8a8263c5a0875ba1c1dacf7824b3ff514a09a5 100644
--- a/src/metabase/api/dataset.clj
+++ b/src/metabase/api/dataset.clj
@@ -112,8 +112,8 @@
 (api/defendpoint-schema ^:streaming POST ["/:export-format", :export-format export-format-regex]
   "Execute a query and download the result data as a file in the specified format."
   [export-format :as {{:keys [query visualization_settings] :or {visualization_settings "{}"}} :params}]
-  {query                  su/JSONStringPlumatic
-   visualization_settings su/JSONStringPlumatic
+  {query                  su/JSONString
+   visualization_settings su/JSONString
    export-format          ExportFormat}
   (let [query        (json/parse-string query keyword)
         viz-settings (-> (json/parse-string visualization_settings viz-setting-key-fn)
diff --git a/src/metabase/api/email.clj b/src/metabase/api/email.clj
index ac219908c4a9a03cd5052abcf72df2f798ef8b39..43bd6faf5dae9a23ed6398920c918effbce1502e 100644
--- a/src/metabase/api/email.clj
+++ b/src/metabase/api/email.clj
@@ -92,7 +92,7 @@
 (api/defendpoint-schema PUT "/"
   "Update multiple email Settings. You must be a superuser or have `setting` permission to do this."
   [:as {settings :body}]
-  {settings su/MapPlumatic}
+  {settings su/Map}
   (validation/check-has-application-permission :setting)
   (let [;; the frontend has access to an obfuscated version of the password. Watch for whether it sent us a new password or
         ;; the obfuscated version
diff --git a/src/metabase/api/embed.clj b/src/metabase/api/embed.clj
index 25356a107b94ae028227412d6248df8e44c158ed..eefa2750a0b9fc813513cc2a8f97500d27d57c66 100644
--- a/src/metabase/api/embed.clj
+++ b/src/metabase/api/embed.clj
@@ -92,7 +92,7 @@
   that ones that are required are specified by checking them against a Card or Dashboard's `object-embedding-params`
   (the object's value of `:embedding_params`). Throws a 400 if any of the checks fail. If all checks are successful,
   returns a *merged* parameters map."
-  [object-embedding-params :- su/EmbeddingParamsPlumatic
+  [object-embedding-params :- su/EmbeddingParams
    token-params            :- {s/Keyword s/Any}
    user-params             :- {s/Keyword s/Any}]
   (check-param-sets object-embedding-params
@@ -115,7 +115,7 @@
   "Remove the `:parameters` for `dashboard-or-card` that listed as `disabled` or `locked` in the `embedding-params`
   whitelist, or not present in the whitelist. This is done so the frontend doesn't display widgets for params the user
   can't set."
-  [dashboard-or-card embedding-params :- su/EmbeddingParamsPlumatic]
+  [dashboard-or-card embedding-params :- su/EmbeddingParams]
   (let [params-to-remove (set (concat (for [[param status] embedding-params
                                             :when          (not= status "enabled")]
                                         param)
@@ -178,7 +178,7 @@
   [card]
   (update card :parameters concat (template-tag-parameters card)))
 
-(s/defn ^:private apply-slug->value :- (s/maybe [{:slug   su/NonBlankStringPlumatic
+(s/defn ^:private apply-slug->value :- (s/maybe [{:slug   su/NonBlankString
                                                   :type   s/Keyword
                                                   :target s/Any
                                                   :value  s/Any}])
@@ -209,7 +209,7 @@
   "Given a `dashboard-id` and parameters map in the format `slug->value`, return a sequence of parameters with `:id`s
   that can be passed to various functions in the `metabase.api.dashboard` namespace such as
   [[metabase.api.dashboard/run-query-for-dashcard-async]]."
-  [dashboard-id :- su/IntGreaterThanZeroPlumatic
+  [dashboard-id :- su/IntGreaterThanZero
    slug->value  :- {s/Any s/Any}]
   (let [parameters (db/select-one-field :parameters Dashboard :id dashboard-id)
         slug->id   (into {} (map (juxt :slug :id)) parameters)]
@@ -468,8 +468,8 @@
 (api/defendpoint-schema GET "/card/:token/field/:field-id/search/:search-field-id"
   "Search for values of a Field that is referenced by an embedded Card."
   [token field-id search-field-id value limit]
-  {value su/NonBlankStringPlumatic
-   limit (s/maybe su/IntStringGreaterThanZeroPlumatic)}
+  {value su/NonBlankString
+   limit (s/maybe su/IntStringGreaterThanZero)}
   (let [unsigned-token (embed/unsign token)
         card-id        (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :question])]
     (check-embedding-enabled-for-card card-id)
@@ -479,8 +479,8 @@
 (api/defendpoint-schema GET "/dashboard/:token/field/:field-id/search/:search-field-id"
   "Search for values of a Field that is referenced by a Card in an embedded Dashboard."
   [token field-id search-field-id value limit]
-  {value su/NonBlankStringPlumatic
-   limit (s/maybe su/IntStringGreaterThanZeroPlumatic)}
+  {value su/NonBlankString
+   limit (s/maybe su/IntStringGreaterThanZero)}
   (let [unsigned-token (embed/unsign token)
         dashboard-id   (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :dashboard])]
     (check-embedding-enabled-for-dashboard dashboard-id)
@@ -495,7 +495,7 @@
   "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with
   embedded Cards."
   [token field-id remapped-id value]
-  {value su/NonBlankStringPlumatic}
+  {value su/NonBlankString}
   (let [unsigned-token (embed/unsign token)
         card-id        (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :question])]
     (check-embedding-enabled-for-card card-id)
@@ -506,7 +506,7 @@
   "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with
   embedded Dashboards."
   [token field-id remapped-id value]
-  {value su/NonBlankStringPlumatic}
+  {value su/NonBlankString}
   (let [unsigned-token (embed/unsign token)
         dashboard-id   (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :dashboard])]
     (check-embedding-enabled-for-dashboard dashboard-id)
@@ -538,7 +538,7 @@
 ;; variables whose name includes `id-` e.g. `id-query-params` below are ones that are keyed by ID; ones whose name
 ;; includes `slug-` are keyed by slug.
 
-(s/defn ^:private param-values-merged-params :- {su/NonBlankStringPlumatic s/Any}
+(s/defn ^:private param-values-merged-params :- {su/NonBlankString s/Any}
   [id->slug slug->id embedding-params token-params id-query-params]
   (let [slug-query-params  (into {}
                                  (for [[id v] id-query-params]
diff --git a/src/metabase/api/field.clj b/src/metabase/api/field.clj
index a0f8b775ad2b0d9b8815a79a0ef2801e8a0f814e..d41e539ecfb01ab8816c982c86d9c259fdffe616 100644
--- a/src/metabase/api/field.clj
+++ b/src/metabase/api/field.clj
@@ -101,17 +101,17 @@
   [id :as {{:keys [caveats description display_name fk_target_field_id points_of_interest semantic_type
                    coercion_strategy visibility_type has_field_values settings nfc_path]
             :as   body} :body}]
-  {caveats            (s/maybe su/NonBlankStringPlumatic)
-   description        (s/maybe su/NonBlankStringPlumatic)
-   display_name       (s/maybe su/NonBlankStringPlumatic)
-   fk_target_field_id (s/maybe su/IntGreaterThanZeroPlumatic)
-   points_of_interest (s/maybe su/NonBlankStringPlumatic)
-   semantic_type      (s/maybe su/FieldSemanticOrRelationTypeKeywordOrStringPlumatic)
-   coercion_strategy  (s/maybe su/CoercionStrategyKeywordOrStringPlumatic)
+  {caveats            (s/maybe su/NonBlankString)
+   description        (s/maybe su/NonBlankString)
+   display_name       (s/maybe su/NonBlankString)
+   fk_target_field_id (s/maybe su/IntGreaterThanZero)
+   points_of_interest (s/maybe su/NonBlankString)
+   semantic_type      (s/maybe su/FieldSemanticOrRelationTypeKeywordOrString)
+   coercion_strategy  (s/maybe su/CoercionStrategyKeywordOrString)
    visibility_type    (s/maybe FieldVisibilityType)
    has_field_values   (s/maybe (apply s/enum (map name field/has-field-values-options)))
-   settings           (s/maybe su/MapPlumatic)
-   nfc_path           (s/maybe [su/NonBlankStringPlumatic])}
+   settings           (s/maybe su/Map)
+   nfc_path           (s/maybe [su/NonBlankString])}
   (let [field              (hydrate (api/write-check Field id) :dimensions)
         new-semantic-type  (keyword (get body :semantic_type (:semantic_type field)))
         [effective-type coercion-strategy]
@@ -169,8 +169,8 @@
   "Sets the dimension for the given field at ID"
   [id :as {{dimension-type :type, dimension-name :name, human_readable_field_id :human_readable_field_id} :body}]
   {dimension-type          (su/api-param "type" (s/enum "internal" "external"))
-   dimension-name          (su/api-param "name" su/NonBlankStringPlumatic)
-   human_readable_field_id (s/maybe su/IntGreaterThanZeroPlumatic)}
+   dimension-name          (su/api-param "name" su/NonBlankString)
+   human_readable_field_id (s/maybe su/IntGreaterThanZero)}
   (api/write-check Field id)
   (api/check (or (= dimension-type "internal")
                  (and (= dimension-type "external")
@@ -278,7 +278,7 @@
   "Update the fields values and human-readable values for a `Field` whose semantic type is
   `category`/`city`/`state`/`country` or whose base type is `type/Boolean`. The human-readable values are optional."
   [id :as {{value-pairs :values} :body}]
-  {value-pairs [[(s/one s/Any "value") (s/optional su/NonBlankStringPlumatic "human readable value")]]}
+  {value-pairs [[(s/one s/Any "value") (s/optional su/NonBlankString "human readable value")]]}
   (let [field (api/write-check Field id)]
     (api/check (field-values/field-should-have-field-values? field)
       [400 (str "You can only update the human readable values of a mapped values of a Field whose value of "
@@ -391,7 +391,7 @@
   "Search for values of a Field with `search-id` that start with `value`. See docstring for
   `metabase.api.field/search-values` for a more detailed explanation."
   [id search-id value]
-  {value su/NonBlankStringPlumatic}
+  {value su/NonBlankString}
   (let [field        (api/check-404 (db/select-one Field :id id))
         search-field (api/check-404 (db/select-one Field :id search-id))]
     (throw-if-no-read-or-segmented-perms field)
diff --git a/src/metabase/api/geojson.clj b/src/metabase/api/geojson.clj
index 96fe5ab5d0c1807f774923185d82633e1bb57250..332367a1cf531203df62dffe1164ef92a8667d44 100644
--- a/src/metabase/api/geojson.clj
+++ b/src/metabase/api/geojson.clj
@@ -24,8 +24,8 @@
   :default    true)
 
 (def ^:private CustomGeoJSON
-  {s/Keyword {:name                     su/NonBlankStringPlumatic
-              :url                      su/NonBlankStringPlumatic
+  {s/Keyword {:name                     su/NonBlankString
+              :url                      su/NonBlankString
               :region_key               (s/maybe s/Str)
               :region_name              (s/maybe s/Str)
               (s/optional-key :builtin) s/Bool}})
@@ -121,7 +121,7 @@
   "Fetch a custom GeoJSON file as defined in the `custom-geojson` setting. (This just acts as a simple proxy for the
   file specified for `key`)."
   [{{:keys [key]} :params} respond raise]
-  {key su/NonBlankStringPlumatic}
+  {key su/NonBlankString}
   (when-not (or (custom-geojson-enabled) (builtin-geojson (keyword key)))
     (raise (ex-info (tru "Custom GeoJSON is not enabled") {:status-code 400})))
   (if-let [url (get-in (custom-geojson) [(keyword key) :url])]
@@ -136,7 +136,7 @@
   "Load a custom GeoJSON file based on a URL or file path provided as a query parameter.
   This behaves similarly to /api/geojson/:key but doesn't require the custom map to be saved to the DB first."
   [{{:keys [url]} :params} respond raise]
-  {url su/NonBlankStringPlumatic}
+  {url su/NonBlankString}
   (validation/check-has-application-permission :setting)
   (when-not (custom-geojson-enabled)
     (raise (ex-info (tru "Custom GeoJSON is not enabled") {:status-code 400})))
diff --git a/src/metabase/api/ldap.clj b/src/metabase/api/ldap.clj
index 38655e7dcb6a1f1e237aac1439a8b74d31ac6f60..f573222e378229eb560547d8d076e6f193262981 100644
--- a/src/metabase/api/ldap.clj
+++ b/src/metabase/api/ldap.clj
@@ -100,7 +100,7 @@
 (api/defendpoint-schema PUT "/settings"
   "Update LDAP related settings. You must be a superuser or have `setting` permission to do this."
   [:as {settings :body}]
-  {settings su/MapPlumatic}
+  {settings su/Map}
   (api/check-superuser)
   (let [ldap-settings (-> settings
                           (select-keys (keys ldap/mb-settings->ldap-details))
diff --git a/src/metabase/api/metric.clj b/src/metabase/api/metric.clj
index 69353d5cca082023785b85b69f5a4106c1aad987..cafca0db4f8df636b749aa71f0ab5f5f8b3f44b0 100644
--- a/src/metabase/api/metric.clj
+++ b/src/metabase/api/metric.clj
@@ -24,9 +24,9 @@
 (api/defendpoint-schema POST "/"
   "Create a new `Metric`."
   [:as {{:keys [name description table_id definition], :as body} :body}]
-  {name        su/NonBlankStringPlumatic
-   table_id    su/IntGreaterThanZeroPlumatic
-   definition  su/MapPlumatic
+  {name        su/NonBlankString
+   table_id    su/IntGreaterThanZero
+   definition  su/Map
    description (s/maybe s/Str)}
   ;; TODO - why can't set the other properties like `show_in_getting_started` when you create a Metric?
   (api/create-check Metric body)
@@ -40,7 +40,7 @@
     (-> (events/publish-event! :metric-create metric)
         (hydrate :creator))))
 
-(s/defn ^:private hydrated-metric [id :- su/IntGreaterThanZeroPlumatic]
+(s/defn ^:private hydrated-metric [id :- su/IntGreaterThanZero]
   (-> (api/read-check (db/select-one Metric :id id))
       (hydrate :creator)))
 
@@ -104,9 +104,9 @@
   [id :as {{:keys [name definition revision_message archived caveats description how_is_this_calculated
                    points_of_interest show_in_getting_started]
             :as   body} :body}]
-  {name                    (s/maybe su/NonBlankStringPlumatic)
-   definition              (s/maybe su/MapPlumatic)
-   revision_message        su/NonBlankStringPlumatic
+  {name                    (s/maybe su/NonBlankString)
+   definition              (s/maybe su/Map)
+   revision_message        su/NonBlankString
    archived                (s/maybe s/Bool)
    caveats                 (s/maybe s/Str)
    description             (s/maybe s/Str)
@@ -120,7 +120,7 @@
   "Update the important `Fields` for a `Metric` with ID.
    (This is used for the Getting Started guide)."
   [id :as {{:keys [important_field_ids]} :body}]
-  {important_field_ids [su/IntGreaterThanZeroPlumatic]}
+  {important_field_ids [su/IntGreaterThanZero]}
   (api/check-superuser)
   (api/write-check Metric id)
   (api/check (<= (count important_field_ids) 3)
@@ -141,7 +141,7 @@
 (api/defendpoint-schema DELETE "/:id"
   "Archive a Metric. (DEPRECATED -- Just pass updated value of `:archived` to the `PUT` endpoint instead.)"
   [id revision_message]
-  {revision_message su/NonBlankStringPlumatic}
+  {revision_message su/NonBlankString}
   (log/warn
    (trs "DELETE /api/metric/:id is deprecated. Instead, change its `archived` value via PUT /api/metric/:id."))
   (write-check-and-update-metric! id {:archived true, :revision_message revision_message})
@@ -160,7 +160,7 @@
 (api/defendpoint-schema POST "/:id/revert"
   "Revert a `Metric` to a prior `Revision`."
   [id :as {{:keys [revision_id]} :body}]
-  {revision_id su/IntGreaterThanZeroPlumatic}
+  {revision_id su/IntGreaterThanZero}
   (api/write-check Metric id)
   (revision/revert!
     :entity      Metric
diff --git a/src/metabase/api/native_query_snippet.clj b/src/metabase/api/native_query_snippet.clj
index 048f105551c4a41ebf17419480e1a93d6f7e7afe..db0c63c7d0df9295f05eac584622f14daee6dd8d 100644
--- a/src/metabase/api/native_query_snippet.clj
+++ b/src/metabase/api/native_query_snippet.clj
@@ -16,7 +16,7 @@
    [toucan.hydrate :refer [hydrate]]))
 
 (s/defn ^:private hydrated-native-query-snippet :- (s/maybe (mi/InstanceOf NativeQuerySnippet))
-  [id :- su/IntGreaterThanZeroPlumatic]
+  [id :- su/IntGreaterThanZero]
   (-> (api/read-check (db/select-one NativeQuerySnippet :id id))
       (hydrate :creator)))
 
@@ -24,7 +24,7 @@
 (api/defendpoint-schema GET "/"
   "Fetch all snippets"
   [archived]
-  {archived (s/maybe su/BooleanStringPlumatic)}
+  {archived (s/maybe su/BooleanString)}
   (let [snippets (db/select NativeQuerySnippet
                             :archived (Boolean/parseBoolean archived)
                             {:order-by [[:%lower.name :asc]]})]
@@ -48,7 +48,7 @@
   {content       s/Str
    description   (s/maybe s/Str)
    name          native-query-snippet/NativeQuerySnippetName
-   collection_id (s/maybe su/IntGreaterThanZeroPlumatic)}
+   collection_id (s/maybe su/IntGreaterThanZero)}
   (check-snippet-name-is-unique name)
   (let [snippet {:content       content
                  :creator_id    api/*current-user-id*
@@ -82,7 +82,7 @@
    content       (s/maybe s/Str)
    description   (s/maybe s/Str)
    name          (s/maybe native-query-snippet/NativeQuerySnippetName)
-   collection_id (s/maybe su/IntGreaterThanZeroPlumatic)}
+   collection_id (s/maybe su/IntGreaterThanZero)}
   (check-perms-and-update-snippet! id body))
 
 (api/define-routes)
diff --git a/src/metabase/api/notify.clj b/src/metabase/api/notify.clj
index 9d7217205f3fdaf106586fc86c207a4d79c79635..4d43fde3107d038025f1d208be111a49d65cad06 100644
--- a/src/metabase/api/notify.clj
+++ b/src/metabase/api/notify.clj
@@ -20,8 +20,8 @@
   This endpoint is secured by an API key that needs to be passed as a `X-METABASE-APIKEY` header which needs to be defined in
   the `MB_API_KEY` [environment variable](https://www.metabase.com/docs/latest/configuring-metabase/environment-variables.html#mb_api_key)"
   [id :as {{:keys [table_id table_name scan synchronous?]} :body}]
-  {table_id   (s/maybe su/IntGreaterThanZeroPlumatic)
-   table_name (s/maybe su/NonBlankStringPlumatic)
+  {table_id   (s/maybe su/IntGreaterThanZero)
+   table_name (s/maybe su/NonBlankString)
    scan       (s/maybe (s/enum "full" "schema"))}
   (let [schema?       (when scan (#{"schema" :schema} scan))
         table-sync-fn (if schema? sync-metadata/sync-table-metadata! sync/sync-table!)
diff --git a/src/metabase/api/permissions.clj b/src/metabase/api/permissions.clj
index c5b43702da1a5f4786b5d68ffb5bcdbf710fe9ce..126e75a28f73795ee7c0b33d06af5ca3ee68e139 100644
--- a/src/metabase/api/permissions.clj
+++ b/src/metabase/api/permissions.clj
@@ -60,7 +60,7 @@
   response will be returned if this key is present and the server is not running the Enterprise Edition, and/or the
   `:sandboxes` feature flag is not present."
   [:as {body :body}]
-  {body su/MapPlumatic}
+  {body su/Map}
   (api/check-superuser)
   (let [graph (api.permission-graph/converted-json->graph ::api.permission-graph/data-permissions-graph body)]
     (when (= graph :clojure.spec.alpha/invalid)
@@ -145,7 +145,7 @@
 (api/defendpoint-schema POST "/group"
   "Create a new `PermissionsGroup`."
   [:as {{:keys [name]} :body}]
-  {name su/NonBlankStringPlumatic}
+  {name su/NonBlankString}
   (api/check-superuser)
   (db/insert! PermissionsGroup
     :name name))
@@ -154,7 +154,7 @@
 (api/defendpoint-schema PUT "/group/:group-id"
   "Update the name of a `PermissionsGroup`."
   [group-id :as {{:keys [name]} :body}]
-  {name su/NonBlankStringPlumatic}
+  {name su/NonBlankString}
   (validation/check-manager-of-group group-id)
   (api/check-404 (db/exists? PermissionsGroup :id group-id))
   (db/update! PermissionsGroup group-id
@@ -199,8 +199,8 @@
 (api/defendpoint-schema POST "/membership"
   "Add a `User` to a `PermissionsGroup`. Returns updated list of members belonging to the group."
   [:as {{:keys [group_id user_id is_group_manager]} :body}]
-  {group_id         su/IntGreaterThanZeroPlumatic
-   user_id          su/IntGreaterThanZeroPlumatic
+  {group_id         su/IntGreaterThanZero
+   user_id          su/IntGreaterThanZero
    is_group_manager (schema.core/maybe schema.core/Bool)}
   (let [is_group_manager (boolean is_group_manager)]
     (validation/check-manager-of-group group_id)
@@ -275,7 +275,7 @@
   modifies it before you can submit you revisions, the endpoint will instead make no changes and return a
   409 (Conflict) response. In this case, you should fetch the updated graph and make desired changes to that."
   [:as {body :body}]
-  {body su/MapPlumatic}
+  {body su/Map}
   (api/check-superuser)
   (let [graph (api.permission-graph/converted-json->graph ::api.permission-graph/execution-permissions-graph body)]
     (when (= graph :clojure.spec.alpha/invalid)
diff --git a/src/metabase/api/persist.clj b/src/metabase/api/persist.clj
index e11c9401875c2b097ea6916c4dc7e11d0f89673e..acc2626a47c9772721536f9a2d4b6fdbe0d75f4f 100644
--- a/src/metabase/api/persist.clj
+++ b/src/metabase/api/persist.clj
@@ -81,7 +81,7 @@
 (api/defendpoint-schema GET "/:persisted-info-id"
   "Fetch a particular [[PersistedInfo]] by id."
   [persisted-info-id]
-  {persisted-info-id (s/maybe su/IntGreaterThanZeroPlumatic)}
+  {persisted-info-id (s/maybe su/IntGreaterThanZero)}
   (api/let-404 [persisted-info (first (fetch-persisted-info {:persisted-info-id persisted-info-id} nil nil))]
     (api/write-check (db/select-one Database :id (:database_id persisted-info)))
     persisted-info))
@@ -90,7 +90,7 @@
 (api/defendpoint-schema GET "/card/:card-id"
   "Fetch a particular [[PersistedInfo]] by card-id."
   [card-id]
-  {card-id (s/maybe su/IntGreaterThanZeroPlumatic)}
+  {card-id (s/maybe su/IntGreaterThanZero)}
   (api/let-404 [persisted-info (first (fetch-persisted-info {:card-id card-id} nil nil))]
     (api/write-check (db/select-one Database :id (:database_id persisted-info)))
     persisted-info))
diff --git a/src/metabase/api/public.clj b/src/metabase/api/public.clj
index 87a0152ab28a8e885aa2f2158316a0a0085a2780..ef1b4aa4763bf670a1e1ea5d54924501e71a2ce7 100644
--- a/src/metabase/api/public.clj
+++ b/src/metabase/api/public.clj
@@ -148,7 +148,7 @@
   "Fetch a publicly-accessible Card an return query results as well as `:card` information. Does not require auth
    credentials. Public sharing must be enabled."
   [uuid parameters]
-  {parameters (s/maybe su/JSONStringPlumatic)}
+  {parameters (s/maybe su/JSONString)}
   (run-query-for-card-with-public-uuid-async uuid :api (json/parse-string parameters keyword)))
 
 #_{:clj-kondo/ignore [:deprecated-var]}
@@ -156,7 +156,7 @@
   "Fetch a publicly-accessible Card and return query results in the specified format. Does not require auth
    credentials. Public sharing must be enabled."
   [uuid export-format :as {{:keys [parameters]} :params}]
-  {parameters    (s/maybe su/JSONStringPlumatic)
+  {parameters    (s/maybe su/JSONString)
    export-format api.dataset/ExportFormat}
   (run-query-for-card-with-public-uuid-async
    uuid
@@ -231,7 +231,7 @@
   "Fetch the results for a Card in a publicly-accessible Dashboard. Does not require auth credentials. Public
    sharing must be enabled."
   [uuid card-id dashcard-id parameters]
-  {parameters (s/maybe su/JSONStringPlumatic)}
+  {parameters (s/maybe su/JSONString)}
   (validation/check-public-sharing-enabled)
   (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))]
     (public-dashcard-results-async
@@ -245,8 +245,8 @@
 (api/defendpoint-schema GET "/dashboard/:uuid/dashcard/:dashcard-id/execute"
   "Fetches the values for filling in execution parameters. Pass PK parameters and values to select."
   [uuid dashcard-id parameters]
-  {dashcard-id su/IntGreaterThanZeroPlumatic
-   parameters su/JSONStringPlumatic}
+  {dashcard-id su/IntGreaterThanZero
+   parameters su/JSONString}
   (validation/check-public-sharing-enabled)
   (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))]
     (actions.execution/fetch-values dashboard-id dashcard-id (json/parse-string parameters))))
@@ -260,7 +260,7 @@
    `parameters` should be the mapped dashboard parameters with values.
    `extra_parameters` should be the extra, user entered parameter values."
   [uuid dashcard-id :as {{:keys [parameters], :as _body} :body}]
-  {dashcard-id su/IntGreaterThanZeroPlumatic
+  {dashcard-id su/IntGreaterThanZero
    parameters (s/maybe {s/Keyword s/Any})}
   (let [throttle-message (try
                            (throttle/check dashcard-execution-throttle dashcard-id)
@@ -289,10 +289,10 @@
   [url format maxheight maxwidth]
   ;; the format param is not used by the API, but is required as part of the oEmbed spec: http://oembed.com/#section2
   ;; just return an error if `format` is specified and it's anything other than `json`.
-  {url       su/NonBlankStringPlumatic
+  {url       su/NonBlankString
    format    (s/maybe (s/enum "json"))
-   maxheight (s/maybe su/IntStringPlumatic)
-   maxwidth  (s/maybe su/IntStringPlumatic)}
+   maxheight (s/maybe su/IntString)
+   maxwidth  (s/maybe su/IntString)}
   (let [height (if maxheight (Integer/parseInt maxheight) default-embed-max-height)
         width  (if maxwidth  (Integer/parseInt maxwidth)  default-embed-max-width)]
     {:version "1.0"
@@ -408,8 +408,8 @@
 (api/defendpoint-schema GET "/card/:uuid/field/:field-id/search/:search-field-id"
   "Search for values of a Field that is referenced by a public Card."
   [uuid field-id search-field-id value limit]
-  {value su/NonBlankStringPlumatic
-   limit (s/maybe su/IntStringGreaterThanZeroPlumatic)}
+  {value su/NonBlankString
+   limit (s/maybe su/IntStringGreaterThanZero)}
   (validation/check-public-sharing-enabled)
   (let [card-id (db/select-one-id Card :public_uuid uuid, :archived false)]
     (search-card-fields card-id field-id search-field-id value (when limit (Integer/parseInt limit)))))
@@ -418,8 +418,8 @@
 (api/defendpoint-schema GET "/dashboard/:uuid/field/:field-id/search/:search-field-id"
   "Search for values of a Field that is referenced by a Card in a public Dashboard."
   [uuid field-id search-field-id value limit]
-  {value su/NonBlankStringPlumatic
-   limit (s/maybe su/IntStringGreaterThanZeroPlumatic)}
+  {value su/NonBlankString
+   limit (s/maybe su/IntStringGreaterThanZero)}
   (validation/check-public-sharing-enabled)
   (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))]
     (search-dashboard-fields dashboard-id field-id search-field-id value (when limit (Integer/parseInt limit)))))
@@ -452,7 +452,7 @@
   "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with public
   Cards."
   [uuid field-id remapped-id value]
-  {value su/NonBlankStringPlumatic}
+  {value su/NonBlankString}
   (validation/check-public-sharing-enabled)
   (let [card-id (api/check-404 (db/select-one-id Card :public_uuid uuid, :archived false))]
     (card-field-remapped-values card-id field-id remapped-id value)))
@@ -462,7 +462,7 @@
   "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with public
   Dashboards."
   [uuid field-id remapped-id value]
-  {value su/NonBlankStringPlumatic}
+  {value su/NonBlankString}
   (validation/check-public-sharing-enabled)
   (let [dashboard-id (db/select-one-id Dashboard :public_uuid uuid, :archived false)]
     (dashboard-field-remapped-values dashboard-id field-id remapped-id value)))
@@ -493,7 +493,7 @@
   "Fetch a publicly-accessible Card an return query results as well as `:card` information. Does not require auth
    credentials. Public sharing must be enabled."
   [uuid parameters]
-  {parameters (s/maybe su/JSONStringPlumatic)}
+  {parameters (s/maybe su/JSONString)}
   (run-query-for-card-with-public-uuid-async uuid :api (json/parse-string parameters keyword) :qp-runner qp.pivot/run-pivot-query))
 
 #_{:clj-kondo/ignore [:deprecated-var]}
@@ -501,7 +501,7 @@
   "Fetch the results for a Card in a publicly-accessible Dashboard. Does not require auth credentials. Public
    sharing must be enabled."
   [uuid card-id dashcard-id parameters]
-  {parameters (s/maybe su/JSONStringPlumatic)}
+  {parameters (s/maybe su/JSONString)}
   (validation/check-public-sharing-enabled)
   (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))]
     (public-dashcard-results-async
diff --git a/src/metabase/api/pulse.clj b/src/metabase/api/pulse.clj
index 1c4b032f8ebcb6bb21990183ada1fe4cd9b0f962..55c60266e5281d4d1e81b351b2d2ae91c7a339fe 100644
--- a/src/metabase/api/pulse.clj
+++ b/src/metabase/api/pulse.clj
@@ -43,9 +43,9 @@
   associated with that dashboard. If `user_id` is specified, restricts results to pulses or subscriptions
   created by the user, or for which the user is a known recipient."
   [archived dashboard_id user_id]
-  {archived     (s/maybe su/BooleanStringPlumatic)
-   dashboard_id (s/maybe su/IntGreaterThanZeroPlumatic)
-   user_id      (s/maybe su/IntGreaterThanZeroPlumatic)}
+  {archived     (s/maybe su/BooleanString)
+   dashboard_id (s/maybe su/IntGreaterThanZero)
+   user_id      (s/maybe su/IntGreaterThanZero)}
   (as-> (pulse/retrieve-pulses {:archived?    (Boolean/parseBoolean archived)
                                 :dashboard-id dashboard_id
                                 :user-id      user_id}) <>
@@ -64,14 +64,14 @@
 (api/defendpoint-schema POST "/"
   "Create a new `Pulse`."
   [:as {{:keys [name cards channels skip_if_empty collection_id collection_position dashboard_id parameters]} :body}]
-  {name                su/NonBlankStringPlumatic
+  {name                su/NonBlankString
    cards               (su/non-empty [pulse/CoercibleToCardRef])
-   channels            (su/non-empty [su/MapPlumatic])
+   channels            (su/non-empty [su/Map])
    skip_if_empty       (s/maybe s/Bool)
-   collection_id       (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_position (s/maybe su/IntGreaterThanZeroPlumatic)
-   dashboard_id        (s/maybe su/IntGreaterThanZeroPlumatic)
-   parameters          [su/MapPlumatic]}
+   collection_id       (s/maybe su/IntGreaterThanZero)
+   collection_position (s/maybe su/IntGreaterThanZero)
+   dashboard_id        (s/maybe su/IntGreaterThanZero)
+   parameters          [su/Map]}
   (validation/check-has-application-permission :subscription false)
   ;; make sure we are allowed to *read* all the Cards we want to put in this Pulse
   (check-card-read-permissions cards)
@@ -108,13 +108,13 @@
 (api/defendpoint-schema PUT "/:id"
   "Update a Pulse with `id`."
   [id :as {{:keys [name cards channels skip_if_empty collection_id archived parameters], :as pulse-updates} :body}]
-  {name          (s/maybe su/NonBlankStringPlumatic)
+  {name          (s/maybe su/NonBlankString)
    cards         (s/maybe (su/non-empty [pulse/CoercibleToCardRef]))
-   channels      (s/maybe (su/non-empty [su/MapPlumatic]))
+   channels      (s/maybe (su/non-empty [su/Map]))
    skip_if_empty (s/maybe s/Bool)
-   collection_id (s/maybe su/IntGreaterThanZeroPlumatic)
+   collection_id (s/maybe su/IntGreaterThanZero)
    archived      (s/maybe s/Bool)
-   parameters    [su/MapPlumatic]}
+   parameters    [su/Map]}
   ;; do various perms checks
   (try
    (validation/check-has-application-permission :monitoring)
@@ -243,13 +243,13 @@
 (api/defendpoint-schema POST "/test"
   "Test send an unsaved pulse."
   [:as {{:keys [name cards channels skip_if_empty collection_id collection_position dashboard_id] :as body} :body}]
-  {name                su/NonBlankStringPlumatic
+  {name                su/NonBlankString
    cards               (su/non-empty [pulse/CoercibleToCardRef])
-   channels            (su/non-empty [su/MapPlumatic])
+   channels            (su/non-empty [su/Map])
    skip_if_empty       (s/maybe s/Bool)
-   collection_id       (s/maybe su/IntGreaterThanZeroPlumatic)
-   collection_position (s/maybe su/IntGreaterThanZeroPlumatic)
-   dashboard_id        (s/maybe su/IntGreaterThanZeroPlumatic)}
+   collection_id       (s/maybe su/IntGreaterThanZero)
+   collection_position (s/maybe su/IntGreaterThanZero)
+   dashboard_id        (s/maybe su/IntGreaterThanZero)}
   (check-card-read-permissions cards)
   ;; make sure any email addresses that are specified are allowed before sending the test Pulse.
   (doseq [channel channels]
diff --git a/src/metabase/api/search.clj b/src/metabase/api/search.clj
index 339dd29a3506b5db12ac093d090bde6b59874b27..f77e59ce4e365cbdf6e4582cbc48c519fa072eb8 100644
--- a/src/metabase/api/search.clj
+++ b/src/metabase/api/search.clj
@@ -30,10 +30,10 @@
 
 (def ^:private SearchContext
   "Map with the various allowed search parameters, used to construct the SQL query"
-  {:search-string                (s/maybe su/NonBlankStringPlumatic)
+  {:search-string                (s/maybe su/NonBlankString)
    :archived?                    s/Bool
    :current-user-perms           #{perms/Path}
-   (s/optional-key :models)      (s/maybe #{su/NonBlankStringPlumatic})
+   (s/optional-key :models)      (s/maybe #{su/NonBlankString})
    (s/optional-key :table-db-id) (s/maybe s/Int)
    (s/optional-key :limit-int)   (s/maybe s/Int)
    (s/optional-key :offset-int)  (s/maybe s/Int)})
@@ -223,7 +223,7 @@
 (s/defn ^:private add-collection-join-and-where-clauses
   "Add a `WHERE` clause to the query to only return Collections the Current User has access to; join against Collection
   so we can return its `:name`."
-  [honeysql-query :- su/MapPlumatic, collection-id-column :- s/Keyword, {:keys [current-user-perms]} :- SearchContext]
+  [honeysql-query :- su/Map, collection-id-column :- s/Keyword, {:keys [current-user-perms]} :- SearchContext]
   (let [visible-collections      (collection/permissions-set->visible-collection-ids current-user-perms)
         collection-filter-clause (collection/visible-collection-ids->honeysql-filter-clause
                                   collection-id-column
@@ -240,7 +240,7 @@
 (s/defn ^:private add-table-db-id-clause
   "Add a WHERE clause to only return tables with the given DB id.
   Used in data picker for joins because we can't join across DB's."
-  [query :- su/MapPlumatic, id :- (s/maybe s/Int)]
+  [query :- su/Map, id :- (s/maybe s/Int)]
   (if (some? id)
     (hh/merge-where query [:= id :db_id])
     query))
@@ -248,7 +248,7 @@
 (s/defn ^:private add-card-db-id-clause
   "Add a WHERE clause to only return cards with the given DB id.
   Used in data picker for joins because we can't join across DB's."
-  [query :- su/MapPlumatic, id :- (s/maybe s/Int)]
+  [query :- su/Map, id :- (s/maybe s/Int)]
   (if (some? id)
     (hh/merge-where query [:= id :database_id])
     query))
@@ -446,15 +446,15 @@
 ;;; +----------------------------------------------------------------------------------------------------------------+
 
 ; This is basically a union type. defendpoint splits the string if it only gets one
-(def ^:private models-schema (s/conditional vector? [su/NonBlankStringPlumatic] :else su/NonBlankStringPlumatic))
+(def ^:private models-schema (s/conditional vector? [su/NonBlankString] :else su/NonBlankString))
 
 (s/defn ^:private search-context :- SearchContext
-  [search-string :-   (s/maybe su/NonBlankStringPlumatic),
-   archived-string :- (s/maybe su/BooleanStringPlumatic)
-   table-db-id :-     (s/maybe su/IntGreaterThanZeroPlumatic)
+  [search-string :-   (s/maybe su/NonBlankString),
+   archived-string :- (s/maybe su/BooleanString)
+   table-db-id :-     (s/maybe su/IntGreaterThanZero)
    models :-          (s/maybe models-schema)
-   limit :-           (s/maybe su/IntGreaterThanZeroPlumatic)
-   offset :-          (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)]
+   limit :-           (s/maybe su/IntGreaterThanZero)
+   offset :-          (s/maybe su/IntGreaterThanOrEqualToZero)]
   (cond-> {:search-string      search-string
            :archived?          (Boolean/parseBoolean archived-string)
            :current-user-perms @api/*current-user-permissions-set*}
@@ -480,9 +480,9 @@
   To specify a list of models, pass in an array to `models`.
   "
   [q archived table_db_id models]
-  {q            (s/maybe su/NonBlankStringPlumatic)
-   archived     (s/maybe su/BooleanStringPlumatic)
-   table_db_id  (s/maybe su/IntGreaterThanZeroPlumatic)
+  {q            (s/maybe su/NonBlankString)
+   archived     (s/maybe su/BooleanString)
+   table_db_id  (s/maybe su/IntGreaterThanZero)
    models       (s/maybe models-schema)}
   (api/check-valid-page-params mw.offset-paging/*limit* mw.offset-paging/*offset*)
   (search (search-context
diff --git a/src/metabase/api/segment.clj b/src/metabase/api/segment.clj
index 4041f7daaff56c6b6c465854185f5d076adb77a5..e1b92291dac736ecfdc10adbde06bd81feb15bfa 100644
--- a/src/metabase/api/segment.clj
+++ b/src/metabase/api/segment.clj
@@ -23,9 +23,9 @@
 (api/defendpoint-schema POST "/"
   "Create a new `Segment`."
   [:as {{:keys [name description table_id definition], :as body} :body}]
-  {name       su/NonBlankStringPlumatic
-   table_id   su/IntGreaterThanZeroPlumatic
-   definition su/MapPlumatic
+  {name       su/NonBlankString
+   table_id   su/IntGreaterThanZero
+   definition su/Map
    description (s/maybe s/Str)}
   ;; TODO - why can't we set other properties like `show_in_getting_started` when we create the Segment?
   (api/create-check Segment body)
@@ -39,7 +39,7 @@
     (-> (events/publish-event! :segment-create segment)
         (hydrate :creator))))
 
-(s/defn ^:private hydrated-segment [id :- su/IntGreaterThanZeroPlumatic]
+(s/defn ^:private hydrated-segment [id :- su/IntGreaterThanZero]
   (-> (api/read-check (db/select-one Segment :id id))
       (hydrate :creator)))
 
@@ -94,9 +94,9 @@
   [id :as {{:keys [name definition revision_message archived caveats description points_of_interest
                    show_in_getting_started]
             :as   body} :body}]
-  {name                    (s/maybe su/NonBlankStringPlumatic)
-   definition              (s/maybe su/MapPlumatic)
-   revision_message        su/NonBlankStringPlumatic
+  {name                    (s/maybe su/NonBlankString)
+   definition              (s/maybe su/Map)
+   revision_message        su/NonBlankString
    archived                (s/maybe s/Bool)
    caveats                 (s/maybe s/Str)
    description             (s/maybe s/Str)
@@ -108,7 +108,7 @@
 (api/defendpoint-schema DELETE "/:id"
   "Archive a Segment. (DEPRECATED -- Just pass updated value of `:archived` to the `PUT` endpoint instead.)"
   [id revision_message]
-  {revision_message su/NonBlankStringPlumatic}
+  {revision_message su/NonBlankString}
   (log/warn
    (trs "DELETE /api/segment/:id is deprecated. Instead, change its `archived` value via PUT /api/segment/:id."))
   (write-check-and-update-segment! id {:archived true, :revision_message revision_message})
@@ -127,7 +127,7 @@
 (api/defendpoint-schema POST "/:id/revert"
   "Revert a `Segement` to a prior `Revision`."
   [id :as {{:keys [revision_id]} :body}]
-  {revision_id su/IntGreaterThanZeroPlumatic}
+  {revision_id su/IntGreaterThanZero}
   (api/write-check Segment id)
   (revision/revert!
     :entity      Segment
diff --git a/src/metabase/api/session.clj b/src/metabase/api/session.clj
index 94292f1dd9f92dd88621cba5c1a00eebced4e7b9..ee356e0f71424aadaf61f2d9054012b2c1f6a7a8 100644
--- a/src/metabase/api/session.clj
+++ b/src/metabase/api/session.clj
@@ -32,7 +32,7 @@
    (java.util UUID)))
 
 (s/defn ^:private record-login-history!
-  [session-id :- UUID user-id :- su/IntGreaterThanZeroPlumatic device-info :- request.u/DeviceInfo]
+  [session-id :- UUID user-id :- su/IntGreaterThanZero device-info :- request.u/DeviceInfo]
   (db/insert! LoginHistory (merge {:user_id    user-id
                                    :session_id (str session-id)}
                                   device-info)))
@@ -45,7 +45,7 @@
     session-type))
 
 (def ^:private CreateSessionUserInfo
-  {:id         su/IntGreaterThanZeroPlumatic
+  {:id         su/IntGreaterThanZero
    :last_login s/Any
    s/Keyword   s/Any})
 
@@ -140,7 +140,7 @@
 (s/defn ^:private login :- {:id UUID, :type (s/enum :normal :full-app-embed), s/Keyword s/Any}
   "Attempt to login with different avaialable methods with `username` and `password`, returning new Session ID or
   throwing an Exception if login could not be completed."
-  [username :- su/NonBlankStringPlumatic password :- su/NonBlankStringPlumatic device-info :- request.u/DeviceInfo]
+  [username :- su/NonBlankString password :- su/NonBlankString device-info :- request.u/DeviceInfo]
   ;; Primitive "strategy implementation", should be reworked for modular providers in #3210
   (or (ldap-login username password device-info)  ; First try LDAP if it's enabled
       (email-login username password device-info) ; Then try local authentication
@@ -167,8 +167,8 @@
 (api/defendpoint-schema POST "/"
   "Login."
   [:as {{:keys [username password]} :body, :as request}]
-  {username su/NonBlankStringPlumatic
-   password su/NonBlankStringPlumatic}
+  {username su/NonBlankString
+   password su/NonBlankString}
   (let [ip-address   (request.u/ip-address request)
         request-time (t/zoned-date-time (t/zone-id "GMT"))
         do-login     (fn []
@@ -224,7 +224,7 @@
 (api/defendpoint-schema POST "/forgot_password"
   "Send a reset email when user has forgotten their password."
   [:as {{:keys [email]} :body, :as request}]
-  {email su/EmailPlumatic}
+  {email su/Email}
   ;; Don't leak whether the account doesn't exist, just pretend everything is ok
   (let [request-source (request.u/ip-address request)]
     (throttle-check (forgot-password-throttlers :ip-address) request-source))
@@ -256,8 +256,8 @@
 (api/defendpoint-schema POST "/reset_password"
   "Reset password with a reset token."
   [:as {{:keys [token password]} :body, :as request}]
-  {token    su/NonBlankStringPlumatic
-   password su/ValidPasswordPlumatic}
+  {token    su/NonBlankString
+   password su/ValidPassword}
   (or (when-let [{user-id :id, :as user} (valid-reset-token->user token)]
         (user/set-password! user-id password)
         ;; if this is the first time the user has logged in it means that they're just accepted their Metabase invite.
@@ -293,7 +293,7 @@
 (api/defendpoint-schema POST "/google_auth"
   "Login with Google Auth."
   [:as {{:keys [token]} :body, :as request}]
-  {token su/NonBlankStringPlumatic}
+  {token su/NonBlankString}
   (when-not (google/google-auth-client-id)
     (throw (ex-info "Google Auth is disabled." {:status-code 400})))
   ;; Verify the token is valid with Google
diff --git a/src/metabase/api/setting.clj b/src/metabase/api/setting.clj
index 68f7926f02ba052567132cf998812bf569cdb5ee..e67c78792aa51bb2761f6373a4671790e443283c 100644
--- a/src/metabase/api/setting.clj
+++ b/src/metabase/api/setting.clj
@@ -52,7 +52,7 @@
   "Create/update a `Setting`. If called by a non-admin, only user-local settings can be updated.
    This endpoint can also be used to delete Settings by passing `nil` for `:value`."
   [key :as {{:keys [value]} :body}]
-  {key su/NonBlankStringPlumatic}
+  {key su/NonBlankString}
   (with-setting-access-control
     (setting/set! key value))
   api/generic-204-no-content)
diff --git a/src/metabase/api/setup.clj b/src/metabase/api/setup.clj
index 7b732da1c8f33fd93e23ffcfc5e7e0b4d8aa497d..550803bd8353fb11dde54297ca97cbd100481e0d 100644
--- a/src/metabase/api/setup.clj
+++ b/src/metabase/api/setup.clj
@@ -39,7 +39,7 @@
 
 (def ^:private SetupToken
   "Schema for a string that matches the instance setup token."
-  (su/with-api-error-message (s/constrained su/NonBlankStringPlumatic setup/token-match?)
+  (su/with-api-error-message (s/constrained su/NonBlankString setup/token-match?)
     "Token does not match the setup token."))
 
 (def ^:dynamic ^:private *allow-api-setup-after-first-user-is-created*
@@ -123,16 +123,16 @@
           invited_email      :email}                    :invite
          {:keys [allow_tracking site_name site_locale]} :prefs} :body, :as request}]
   {token              SetupToken
-   site_name          su/NonBlankStringPlumatic
-   site_locale        (s/maybe su/ValidLocalePlumatic)
-   first_name         (s/maybe su/NonBlankStringPlumatic)
-   last_name          (s/maybe su/NonBlankStringPlumatic)
-   email              su/EmailPlumatic
-   invited_first_name (s/maybe su/NonBlankStringPlumatic)
-   invited_last_name  (s/maybe su/NonBlankStringPlumatic)
-   invited_email      (s/maybe su/EmailPlumatic)
-   password           su/ValidPasswordPlumatic
-   allow_tracking     (s/maybe (s/cond-pre s/Bool su/BooleanStringPlumatic))
+   site_name          su/NonBlankString
+   site_locale        (s/maybe su/ValidLocale)
+   first_name         (s/maybe su/NonBlankString)
+   last_name          (s/maybe su/NonBlankString)
+   email              su/Email
+   invited_first_name (s/maybe su/NonBlankString)
+   invited_last_name  (s/maybe su/NonBlankString)
+   invited_email      (s/maybe su/Email)
+   password           su/ValidPassword
+   allow_tracking     (s/maybe (s/cond-pre s/Bool su/BooleanString))
    schedules          (s/maybe sync.schedules/ExpandedSchedulesMap)
    auto_run_queries   (s/maybe s/Bool)}
   (letfn [(create! []
diff --git a/src/metabase/api/slack.clj b/src/metabase/api/slack.clj
index 13dfd036441f00a36a4731968f14021558aaf51e..4d45ac903df99b758bd1c2a412adf2e346a506a9 100644
--- a/src/metabase/api/slack.clj
+++ b/src/metabase/api/slack.clj
@@ -19,8 +19,8 @@
   2. invalid token         -> clear
   3. truthy, valid token   -> refresh "
   [:as {{slack-app-token :slack-app-token, slack-files-channel :slack-files-channel} :body}]
-  {slack-app-token     (s/maybe su/NonBlankStringPlumatic)
-   slack-files-channel (s/maybe su/NonBlankStringPlumatic)}
+  {slack-app-token     (s/maybe su/NonBlankString)
+   slack-files-channel (s/maybe su/NonBlankString)}
   (validation/check-has-application-permission :setting)
   (try
     (when (and slack-app-token
diff --git a/src/metabase/api/table.clj b/src/metabase/api/table.clj
index 937f0f515af790aafb669e1bf990c2f5a54a52ea..7bb9bfde1cafc569e1ef20ba5654074487678ef5 100644
--- a/src/metabase/api/table.clj
+++ b/src/metabase/api/table.clj
@@ -98,8 +98,8 @@
   "Update `Table` with ID."
   [id :as {{:keys [display_name entity_type visibility_type description caveats points_of_interest
                    show_in_getting_started field_order], :as body} :body}]
-  {display_name            (s/maybe su/NonBlankStringPlumatic)
-   entity_type             (s/maybe su/EntityTypeKeywordOrStringPlumatic)
+  {display_name            (s/maybe su/NonBlankString)
+   entity_type             (s/maybe su/EntityTypeKeywordOrString)
    visibility_type         (s/maybe TableVisibilityType)
    description             (s/maybe s/Str)
    caveats                 (s/maybe s/Str)
@@ -113,9 +113,9 @@
   "Update all `Table` in `ids`."
   [:as {{:keys [ids display_name entity_type visibility_type description caveats points_of_interest
                 show_in_getting_started], :as body} :body}]
-  {ids                     (su/non-empty [su/IntGreaterThanZeroPlumatic])
-   display_name            (s/maybe su/NonBlankStringPlumatic)
-   entity_type             (s/maybe su/EntityTypeKeywordOrStringPlumatic)
+  {ids                     (su/non-empty [su/IntGreaterThanZero])
+   display_name            (s/maybe su/NonBlankString)
+   entity_type             (s/maybe su/EntityTypeKeywordOrString)
    visibility_type         (s/maybe TableVisibilityType)
    description             (s/maybe s/Str)
    caveats                 (s/maybe s/Str)
@@ -307,9 +307,9 @@
 
   These options are provided for use in the Admin Edit Metadata page."
   [id include_sensitive_fields include_hidden_fields include_editable_data_model]
-  {include_sensitive_fields (s/maybe su/BooleanStringPlumatic)
-   include_hidden_fields (s/maybe su/BooleanStringPlumatic)
-   include_editable_data_model (s/maybe su/BooleanStringPlumatic)}
+  {include_sensitive_fields (s/maybe su/BooleanString)
+   include_hidden_fields (s/maybe su/BooleanString)
+   include_editable_data_model (s/maybe su/BooleanString)}
   (fetch-query-metadata (db/select-one Table :id id) {:include-sensitive-fields?    include_sensitive_fields
                                                       :include-hidden-fields?       include_hidden_fields
                                                       :include-editable-data-model? include_editable_data_model}))
@@ -456,7 +456,7 @@
 (api/defendpoint-schema PUT "/:id/fields/order"
   "Reorder fields"
   [id :as {field_order :body}]
-  {field_order [su/IntGreaterThanZeroPlumatic]}
+  {field_order [su/IntGreaterThanZero]}
   (-> (db/select-one Table :id id) api/write-check (table/custom-order-fields! field_order)))
 
 (api/define-routes)
diff --git a/src/metabase/api/tiles.clj b/src/metabase/api/tiles.clj
index 617cd139e03af5b8b926140cdc4dd41e265d0e36..a7448fd4e169c25ba7d719b7252b9122e3a8e73b 100644
--- a/src/metabase/api/tiles.clj
+++ b/src/metabase/api/tiles.clj
@@ -174,12 +174,12 @@
   appropriate ones. It's expected that to render a full map view several calls will be made to this endpoint in
   parallel."
   [zoom x y lat-field lon-field query]
-  {zoom        su/IntStringPlumatic
-   x           su/IntStringPlumatic
-   y           su/IntStringPlumatic
+  {zoom        su/IntString
+   x           su/IntString
+   y           su/IntString
    lat-field   s/Str
    lon-field   s/Str
-   query       su/JSONStringPlumatic}
+   query       su/JSONString}
   (let [zoom          (Integer/parseInt zoom)
         x             (Integer/parseInt x)
         y             (Integer/parseInt y)
diff --git a/src/metabase/api/timeline.clj b/src/metabase/api/timeline.clj
index 30899a6b7e1af551b2a44aaef20b6a157a2752c5..c7519db0300337d8264de7ca82cdb5c73f6c1d0f 100644
--- a/src/metabase/api/timeline.clj
+++ b/src/metabase/api/timeline.clj
@@ -23,11 +23,11 @@
 (api/defendpoint-schema POST "/"
   "Create a new [[Timeline]]."
   [:as {{:keys [name default description icon collection_id archived], :as body} :body}]
-  {name          su/NonBlankStringPlumatic
+  {name          su/NonBlankString
    default       (s/maybe s/Bool)
    description   (s/maybe s/Str)
    icon          (s/maybe timeline/Icons)
-   collection_id (s/maybe su/IntGreaterThanZeroPlumatic)
+   collection_id (s/maybe su/IntGreaterThanZero)
    archived      (s/maybe s/Bool)}
   (collection/check-write-perms-for-collection collection_id)
   (let [tl (merge
@@ -42,7 +42,7 @@
   "Fetch a list of [[Timelines]]. Can include `archived=true` to return archived timelines."
   [include archived]
   {include  (s/maybe Include)
-   archived (s/maybe su/BooleanStringPlumatic)}
+   archived (s/maybe su/BooleanString)}
   (let [archived? (Boolean/parseBoolean archived)
         timelines (->> (db/select Timeline
                          {:where    [:and
@@ -61,9 +61,9 @@
   `archived=true` to return all events on the timeline, both archived and unarchived."
   [id include archived start end]
   {include  (s/maybe Include)
-   archived (s/maybe su/BooleanStringPlumatic)
-   start    (s/maybe su/TemporalStringPlumatic)
-   end      (s/maybe su/TemporalStringPlumatic)}
+   archived (s/maybe su/BooleanString)
+   start    (s/maybe su/TemporalString)
+   end      (s/maybe su/TemporalString)}
   (let [archived? (Boolean/parseBoolean archived)
         timeline  (api/read-check (db/select-one Timeline :id id))]
     (cond-> (hydrate timeline :creator [:collection :can_write])
@@ -82,11 +82,11 @@
   "Update the [[Timeline]] with `id`. Returns the timeline without events. Archiving a timeline will archive all of the
   events in that timeline."
   [id :as {{:keys [name default description icon collection_id archived] :as timeline-updates} :body}]
-  {name          (s/maybe su/NonBlankStringPlumatic)
+  {name          (s/maybe su/NonBlankString)
    default       (s/maybe s/Bool)
    description   (s/maybe s/Str)
    icon          (s/maybe timeline/Icons)
-   collection_id (s/maybe su/IntGreaterThanZeroPlumatic)
+   collection_id (s/maybe su/IntGreaterThanZero)
    archived      (s/maybe s/Bool)}
   (let [existing (api/write-check Timeline id)
         current-archived (:archived (db/select-one Timeline :id id))]
diff --git a/src/metabase/api/timeline_event.clj b/src/metabase/api/timeline_event.clj
index f795d5c86768a2ed9688cd799209bf92a917ec60..42a395401d46a240900325cb7c9b2ec36254c3cc 100644
--- a/src/metabase/api/timeline_event.clj
+++ b/src/metabase/api/timeline_event.clj
@@ -20,15 +20,15 @@
 (api/defendpoint-schema POST "/"
   "Create a new [[TimelineEvent]]."
   [:as {{:keys [name description timestamp time_matters timezone icon timeline_id source question_id archived] :as body} :body}]
-  {name         su/NonBlankStringPlumatic
+  {name         su/NonBlankString
    description  (s/maybe s/Str)
-   timestamp    su/TemporalStringPlumatic
+   timestamp    su/TemporalString
    time_matters (s/maybe s/Bool)
    timezone     s/Str
    icon         (s/maybe timeline/Icons)
-   timeline_id  su/IntGreaterThanZeroPlumatic
+   timeline_id  su/IntGreaterThanZero
    source       (s/maybe timeline-event/Sources)
-   question_id  (s/maybe su/IntGreaterThanZeroPlumatic)
+   question_id  (s/maybe su/IntGreaterThanZero)
    archived     (s/maybe s/Bool)}
   ;; deliberately not using api/check-404 so we can have a useful error message.
   (let [timeline (db/select-one Timeline :id timeline_id)]
@@ -64,13 +64,13 @@
   "Update a [[TimelineEvent]]."
   [id :as {{:keys [name description timestamp time_matters timezone icon timeline_id archived]
             :as   timeline-event-updates} :body}]
-  {name         (s/maybe su/NonBlankStringPlumatic)
+  {name         (s/maybe su/NonBlankString)
    description  (s/maybe s/Str)
-   timestamp    (s/maybe su/TemporalStringPlumatic)
+   timestamp    (s/maybe su/TemporalString)
    time_matters (s/maybe s/Bool)
    timezone     (s/maybe s/Str)
    icon         (s/maybe timeline/Icons)
-   timeline_id  (s/maybe su/IntGreaterThanZeroPlumatic)
+   timeline_id  (s/maybe su/IntGreaterThanZero)
    archived     (s/maybe s/Bool)}
   (let [existing (api/write-check TimelineEvent id)
         timeline-event-updates (cond-> timeline-event-updates
diff --git a/src/metabase/api/user.clj b/src/metabase/api/user.clj
index 30e36a7bb592b56b5ed5526b6f8cfec5a9d0a960..e219455153b9235114cfb84e86e4245c5061daa5 100644
--- a/src/metabase/api/user.clj
+++ b/src/metabase/api/user.clj
@@ -154,8 +154,8 @@
   [status query group_id include_deactivated]
   {status                 (s/maybe s/Str)
    query                  (s/maybe s/Str)
-   group_id               (s/maybe su/IntGreaterThanZeroPlumatic)
-   include_deactivated    (s/maybe su/BooleanStringPlumatic)}
+   group_id               (s/maybe su/IntGreaterThanZero)
+   include_deactivated    (s/maybe su/BooleanString)}
   (when (or status include_deactivated)
     (validation/check-group-manager))
   (let [include_deactivated (Boolean/parseBoolean include_deactivated)]
@@ -245,9 +245,9 @@
 (api/defendpoint-schema POST "/"
   "Create a new `User`, return a 400 if the email address is already taken"
   [:as {{:keys [first_name last_name email user_group_memberships login_attributes] :as body} :body}]
-  {first_name             (s/maybe su/NonBlankStringPlumatic)
-   last_name              (s/maybe su/NonBlankStringPlumatic)
-   email                  su/EmailPlumatic
+  {first_name             (s/maybe su/NonBlankString)
+   last_name              (s/maybe su/NonBlankString)
+   email                  su/Email
    user_group_memberships (s/maybe [user/UserGroupMembership])
    login_attributes       (s/maybe user/LoginAttributes)}
   (api/check-superuser)
@@ -301,14 +301,14 @@
   Group Managers can only add/remove users from groups they are manager of."
   [id :as {{:keys [email first_name last_name user_group_memberships
                    is_superuser is_group_manager login_attributes locale] :as body} :body}]
-  {email                  (s/maybe su/EmailPlumatic)
-   first_name             (s/maybe su/NonBlankStringPlumatic)
-   last_name              (s/maybe su/NonBlankStringPlumatic)
+  {email                  (s/maybe su/Email)
+   first_name             (s/maybe su/NonBlankString)
+   last_name              (s/maybe su/NonBlankString)
    user_group_memberships (s/maybe [user/UserGroupMembership])
    is_superuser           (s/maybe s/Bool)
    is_group_manager       (s/maybe s/Bool)
    login_attributes       (s/maybe user/LoginAttributes)
-   locale                 (s/maybe su/ValidLocalePlumatic)}
+   locale                 (s/maybe su/ValidLocale)}
   (try
     (check-self-or-superuser id)
     (catch clojure.lang.ExceptionInfo _e
@@ -382,7 +382,7 @@
 (api/defendpoint-schema PUT "/:id/password"
   "Update a user's password."
   [id :as {{:keys [password old_password]} :body}]
-  {password su/ValidPasswordPlumatic}
+  {password su/ValidPassword}
   (check-self-or-superuser id)
   (api/let-404 [user (db/select-one [User :password_salt :password], :id id, :is_active true)]
     ;; admins are allowed to reset anyone's password (in the admin people list) so no need to check the value of
diff --git a/src/metabase/api/util.clj b/src/metabase/api/util.clj
index 488c78eb8fe118a1aa2c98835c2e574345e51a1f..d62369ad350a09843c4de5885eac2af8135e137f 100644
--- a/src/metabase/api/util.clj
+++ b/src/metabase/api/util.clj
@@ -16,7 +16,7 @@
 (api/defendpoint-schema POST "/password_check"
   "Endpoint that checks if the supplied password meets the currently configured password complexity rules."
   [:as {{:keys [password]} :body}]
-  {password su/ValidPasswordPlumatic} ;; if we pass the su/ValidPassword test we're g2g
+  {password su/ValidPassword} ;; if we pass the su/ValidPassword test we're g2g
   {:valid true})
 
 #_{:clj-kondo/ignore [:deprecated-var]}
diff --git a/src/metabase/automagic_dashboards/core.clj b/src/metabase/automagic_dashboards/core.clj
index d00e4931c689e6a4740743d92867f6148f3a7c52..cd55a64121a0b334c649358bd958cb2472d98957 100644
--- a/src/metabase/automagic_dashboards/core.clj
+++ b/src/metabase/automagic_dashboards/core.clj
@@ -48,7 +48,7 @@
 (s/defn ->field :- (s/maybe (mi/InstanceOf Field))
   "Return `Field` instance for a given ID or name in the context of root."
   [{{result-metadata :result_metadata} :source, :as root}
-   field-id-or-name-or-clause :- (s/cond-pre su/IntGreaterThanZeroPlumatic su/NonBlankStringPlumatic mbql.s/Field)]
+   field-id-or-name-or-clause :- (s/cond-pre su/IntGreaterThanZero su/NonBlankString mbql.s/Field)]
   (let [id-or-name (if (sequential? field-id-or-name-or-clause)
                      (filters/field-reference->id field-id-or-name-or-clause)
                      field-id-or-name-or-clause)]
diff --git a/src/metabase/automagic_dashboards/filters.clj b/src/metabase/automagic_dashboards/filters.clj
index b25af8064591274d38e1f6cebcd68238badf8d13..72186dfff5a2d0f09875966b7e6c3bdbea652358 100644
--- a/src/metabase/automagic_dashboards/filters.clj
+++ b/src/metabase/automagic_dashboards/filters.clj
@@ -14,7 +14,7 @@
   "Is given form an MBQL field reference?"
   (complement (s/checker mbql.s/field)))
 
-(s/defn field-reference->id :- (s/maybe (s/cond-pre su/NonBlankStringPlumatic su/IntGreaterThanZeroPlumatic))
+(s/defn field-reference->id :- (s/maybe (s/cond-pre su/NonBlankString su/IntGreaterThanZero))
   "Extract field ID from a given field reference form."
   [clause]
   (mbql.u/match-one clause [:field id _] id))
diff --git a/src/metabase/automagic_dashboards/rules.clj b/src/metabase/automagic_dashboards/rules.clj
index f88f4466d05d861e8b8db9b9871a3d4da17064e5..e97e0b255e1cf3a4329fb750b4f727d080d2b835 100644
--- a/src/metabase/automagic_dashboards/rules.clj
+++ b/src/metabase/automagic_dashboards/rules.clj
@@ -80,7 +80,7 @@
 
 (def ^:private OrderByPair {Identifier (s/enum "descending" "ascending")})
 
-(def ^:private Visualization [(s/one s/Str "visualization") su/MapPlumatic])
+(def ^:private Visualization [(s/one s/Str "visualization") su/Map])
 
 (def ^:private Width  (s/constrained s/Int #(<= 1 % populate/grid-width)
                                      (deferred-trs "1 <= width <= {0}" populate/grid-width)))
@@ -96,7 +96,7 @@
                (s/optional-key :dimensions)    [CardDimension]
                (s/optional-key :filters)       [s/Str]
                (s/optional-key :metrics)       [s/Str]
-               (s/optional-key :limit)         su/IntGreaterThanZeroPlumatic
+               (s/optional-key :limit)         su/IntGreaterThanZero
                (s/optional-key :order_by)      [OrderByPair]
                (s/optional-key :description)   LocalizedString
                (s/optional-key :query)         s/Str
@@ -127,7 +127,7 @@
   [(s/one (s/constrained (s/cond-pre s/Str s/Keyword) (comp #{:dimension} qp.util/normalize-token))
           "dimension")
    (s/one s/Str "identifier")
-   su/MapPlumatic])
+   su/Map])
 
 (def ^{:arglists '([form])} dimension-form?
   "Does form denote a dimension referece?"
diff --git a/src/metabase/db/metadata_queries.clj b/src/metabase/db/metadata_queries.clj
index d7bbecae778dd5a3533888c7ff47dc443248f2cb..3291f361caa93d05c11f84e42ee87ac5fe609ee9 100644
--- a/src/metabase/db/metadata_queries.clj
+++ b/src/metabase/db/metadata_queries.clj
@@ -61,7 +61,7 @@
   ([field]
    (field-distinct-values field absolute-max-distinct-values-limit))
 
-  ([field max-results :- su/IntGreaterThanZeroPlumatic]
+  ([field max-results :- su/IntGreaterThanZero]
    (mapv first (field-query field {:breakout [[:field (u/the-id field) nil]]
                                    :limit    (min max-results absolute-max-distinct-values-limit)}))))
 
diff --git a/src/metabase/db/util.clj b/src/metabase/db/util.clj
index ccedabe56f799f522ba846a819e1daaf586beb45..3040c8637816a254704d14e9cd8e73e44779b6c0 100644
--- a/src/metabase/db/util.clj
+++ b/src/metabase/db/util.clj
@@ -18,7 +18,7 @@
 (def ^:private NamespacedKeyword
   (s/constrained s/Keyword (comp seq namespace) "namespaced keyword"))
 
-(s/defn ^:private type-keyword->descendants :- (su/non-empty #{su/NonBlankStringPlumatic})
+(s/defn ^:private type-keyword->descendants :- (su/non-empty #{su/NonBlankString})
   "Return a set of descendents of Metabase `type-keyword`. This includes `type-keyword` itself, so the set will always
   have at least one element.
 
diff --git a/src/metabase/driver/common/parameters/dates.clj b/src/metabase/driver/common/parameters/dates.clj
index f200d61d69e1356d4c21b4915db2a63baa1dc86c..454ed60f8bf806419f5864c006fb5590d637ac20 100644
--- a/src/metabase/driver/common/parameters/dates.clj
+++ b/src/metabase/driver/common/parameters/dates.clj
@@ -403,7 +403,7 @@
 (s/defn date-string->filter :- mbql.s/Filter
   "Takes a string description of a *date* (not datetime) range such as 'lastmonth' or '2016-07-15~2016-08-6' and
    returns a corresponding MBQL filter clause for a given field reference."
-  [date-string :- s/Str field :- (s/cond-pre su/IntGreaterThanZeroPlumatic mbql.s/Field)]
+  [date-string :- s/Str field :- (s/cond-pre su/IntGreaterThanZero mbql.s/Field)]
   (or (execute-decoders all-date-string-decoders :filter (params/wrap-field-id-if-needed field) date-string)
       (throw (ex-info (tru "Don''t know how to parse date string {0}" (pr-str date-string))
                       {:type        qp.error-type/invalid-parameter
diff --git a/src/metabase/driver/common/parameters/values.clj b/src/metabase/driver/common/parameters/values.clj
index 6ede6309ab78e187f59e5ad6bf054b3bf946a707..40c7ea66a864c9048c0eddc5ada64f92f8fde158 100644
--- a/src/metabase/driver/common/parameters/values.clj
+++ b/src/metabase/driver/common/parameters/values.clj
@@ -54,7 +54,7 @@
 
 (def ^:private ParsedParamValue
   "Schema for valid param value(s). Params can have one or more values."
-  (s/named (s/maybe (s/cond-pre params/SingleValue MultipleValues su/MapPlumatic))
+  (s/named (s/maybe (s/cond-pre params/SingleValue MultipleValues su/Map))
            "Valid param value(s)"))
 
 (s/defn ^:private tag-targets
@@ -91,7 +91,7 @@
                 param-display-name)
            {:type qp.error-type/missing-required-parameter}))
 
-(s/defn ^:private field-filter->field-id :- su/IntGreaterThanZeroPlumatic
+(s/defn ^:private field-filter->field-id :- su/IntGreaterThanZero
   [field-filter]
   (second field-filter))
 
@@ -263,7 +263,7 @@
   to parse it as appropriate based on the base type and semantic type of the Field associated with it). These are
   special cases for handling types that do not have an associated parameter type (such as `date` or `number`), such as
   UUID fields."
-  [effective-type :- su/FieldTypePlumatic value]
+  [effective-type :- su/FieldType value]
   (cond
     (isa? effective-type :type/UUID)
     (UUID/fromString value)
@@ -340,7 +340,7 @@
                        :type (or (:type (ex-data e)) qp.error-type/invalid-parameter)}
                       e)))))
 
-(s/defn query->params-map :- {su/NonBlankStringPlumatic ParsedParamValue}
+(s/defn query->params-map :- {su/NonBlankString ParsedParamValue}
   "Extract parameters info from `query`. Return a map of parameter name -> value.
 
     (query->params-map some-query)
diff --git a/src/metabase/driver/sql.clj b/src/metabase/driver/sql.clj
index 7cf7a0f9a5e84f3a781439c54110174be26894b0..0f8ef550a84ea44c6507324b2e4a12d2fbbc2c75 100644
--- a/src/metabase/driver/sql.clj
+++ b/src/metabase/driver/sql.clj
@@ -42,7 +42,7 @@
   (sql.qp/mbql->native driver query))
 
 (s/defmethod driver/substitute-native-parameters :sql
-  [_ {:keys [query] :as inner-query} :- {:query su/NonBlankStringPlumatic, s/Keyword s/Any}]
+  [_ {:keys [query] :as inner-query} :- {:query su/NonBlankString, s/Keyword s/Any}]
   (let [[query params] (-> query
                            params.parse/parse
                            (sql.params.substitute/substitute (params.values/query->params-map inner-query)))]
diff --git a/src/metabase/driver/sql/parameters/substitution.clj b/src/metabase/driver/sql/parameters/substitution.clj
index 0899e2707710f1df92e20ae2d5a680548545b9bd..9b7ac3904e959efd3575c6373d5cfdf5ff5a774a 100644
--- a/src/metabase/driver/sql/parameters/substitution.clj
+++ b/src/metabase/driver/sql/parameters/substitution.clj
@@ -246,7 +246,7 @@
     ;; in case anyone needs to know we're compiling a Field filter.
     ::compiling-field-filter? true}])
 
-(s/defn ^:private field->identifier :- su/NonBlankStringPlumatic
+(s/defn ^:private field->identifier :- su/NonBlankString
   "Return an approprate snippet to represent this `field` in SQL given its param type.
    For non-date Fields, this is just a quoted identifier; for dates, the SQL includes appropriately bucketing based on
    the `param-type`."
diff --git a/src/metabase/driver/sql_jdbc/connection.clj b/src/metabase/driver/sql_jdbc/connection.clj
index cc29f78746e213a583d334100e8d3695225388e8..5e74a8a7938bce01460af10ea440e5db08c80f86 100644
--- a/src/metabase/driver/sql_jdbc/connection.clj
+++ b/src/metabase/driver/sql_jdbc/connection.clj
@@ -161,7 +161,7 @@
 (s/defn ^:private jdbc-spec-hash
   "Computes a hash value for the JDBC connection spec based on `database`'s `:details` map, for the purpose of
   determining if details changed and therefore the existing connection pool needs to be invalidated."
-  [{driver :engine, :keys [details], :as database} :- (s/maybe su/MapPlumatic)]
+  [{driver :engine, :keys [details], :as database} :- (s/maybe su/Map)]
   (when (some? database)
     (hash (connection-details->spec driver details))))
 
diff --git a/src/metabase/driver/util.clj b/src/metabase/driver/util.clj
index 6f3ed2cd8291cefc2868e983b76531dd1ac09411..7c40abfe33febf33b93c214fe2b75eb169b4258f 100644
--- a/src/metabase/driver/util.clj
+++ b/src/metabase/driver/util.clj
@@ -213,7 +213,7 @@
    (semantic-version-gte [4 0 1] [4 1]) => false
    (semantic-version-gte [4 1] [4]) => true
    (semantic-version-gte [3 1] [4]) => false"
-  [xv :- [su/IntGreaterThanOrEqualToZeroPlumatic] yv :- [su/IntGreaterThanOrEqualToZeroPlumatic]] :- s/Bool
+  [xv :- [su/IntGreaterThanOrEqualToZero] yv :- [su/IntGreaterThanOrEqualToZero]] :- s/Bool
   (loop [xv (seq xv), yv (seq yv)]
     (or (nil? yv)
         (let [[x & xs] xv
diff --git a/src/metabase/email.clj b/src/metabase/email.clj
index cabd82820c75889fe96013c268c70488c2deee99..887e8db6325c7c9008a72cecaa9d94ff401155a2 100644
--- a/src/metabase/email.clj
+++ b/src/metabase/email.clj
@@ -27,7 +27,7 @@
   :visibility :settings-manager)
 
 (def ^:private ReplyToAddresses
-  (s/maybe [su/EmailPlumatic]))
+  (s/maybe [su/Email]))
 
 (def ^:private ^{:arglists '([reply-to-addresses])} validate-reply-to-addresses
   (s/validator ReplyToAddresses))
@@ -106,7 +106,7 @@
    {:subject      s/Str
     :recipients   [(s/pred u/email?)]
     :message-type (s/enum :text :html :attachments)
-    :message      (s/cond-pre s/Str [su/MapPlumatic])} ; TODO - what should this be a sequence of?
+    :message      (s/cond-pre s/Str [su/Map])} ; TODO - what should this be a sequence of?
    (fn [{:keys [message-type message]}]
      (if (= message-type :attachments)
        (and (sequential? message) (every? map? message))
@@ -163,8 +163,8 @@
       {::error e})))
 
 (def ^:private SMTPSettings
-  {:host                         su/NonBlankStringPlumatic
-   :port                         su/IntGreaterThanZeroPlumatic
+  {:host                         su/NonBlankString
+   :port                         su/IntGreaterThanZero
      ;; TODO -- not sure which of these other ones are actually required or not, and which are optional.
    (s/optional-key :user)        (s/maybe s/Str)
    (s/optional-key :security)    (s/maybe (s/enum :tls :ssl :none :starttls))
diff --git a/src/metabase/integrations/ldap.clj b/src/metabase/integrations/ldap.clj
index 2d923c89a5ad89d13e0016352f764bf7206b21e1..b504f265603940642b6032b0401fa6124281c421 100644
--- a/src/metabase/integrations/ldap.clj
+++ b/src/metabase/integrations/ldap.clj
@@ -223,11 +223,11 @@
 
 (s/defn find-user :- (s/maybe i/UserInfo)
   "Get user information for the supplied username."
-  ([username :- su/NonBlankStringPlumatic]
+  ([username :- su/NonBlankString]
    (with-ldap-connection [conn]
      (find-user conn username)))
 
-  ([ldap-connection :- LDAPConnectionPool, username :- su/NonBlankStringPlumatic]
+  ([ldap-connection :- LDAPConnectionPool, username :- su/NonBlankString]
    (default-impl/find-user ldap-connection username (ldap-settings))))
 
 (s/defn fetch-or-create-user! :- (mi/InstanceOf User)
diff --git a/src/metabase/integrations/ldap/default_implementation.clj b/src/metabase/integrations/ldap/default_implementation.clj
index 354a83ea4bd41bb82af8d5f79da188c9b9c83c46..2f23da5fdfbc891e76de73d427d9ee9a28c0081e 100644
--- a/src/metabase/integrations/ldap/default_implementation.clj
+++ b/src/metabase/integrations/ldap/default_implementation.clj
@@ -23,10 +23,10 @@
 (def ^:private group-membership-filter
   "(member={dn})")
 
-(s/defn search :- (s/maybe su/MapPlumatic)
+(s/defn search :- (s/maybe su/Map)
   "Search for a LDAP user with `username`."
   [ldap-connection                 :- LDAPConnectionPool
-   username                        :- su/NonBlankStringPlumatic
+   username                        :- su/NonBlankString
    {:keys [user-base user-filter]} :- i/LDAPSettings]
   (some-> (first
            (ldap/search
@@ -37,23 +37,23 @@
              :size-limit 1}))
           u/lower-case-map-keys))
 
-(s/defn ^:private process-group-membership-filter :- su/NonBlankStringPlumatic
+(s/defn ^:private process-group-membership-filter :- su/NonBlankString
   "Replace DN and UID placeholders with values returned by the LDAP server."
-  [group-membership-filter :- su/NonBlankStringPlumatic
-   dn                      :- su/NonBlankStringPlumatic
-   uid                     :- (s/maybe su/NonBlankStringPlumatic)]
+  [group-membership-filter :- su/NonBlankString
+   dn                      :- su/NonBlankString
+   uid                     :- (s/maybe su/NonBlankString)]
   (let [uid-string (or uid "")]
     (-> group-membership-filter
         (str/replace "{dn}" (Filter/encodeValue ^String dn))
         (str/replace "{uid}" (Filter/encodeValue ^String uid-string)))))
 
-(s/defn ^:private user-groups :- (s/maybe [su/NonBlankStringPlumatic])
+(s/defn ^:private user-groups :- (s/maybe [su/NonBlankString])
   "Retrieve groups for a supplied DN."
   [ldap-connection         :- LDAPConnectionPool
-   dn                      :- su/NonBlankStringPlumatic
-   uid                     :- (s/maybe su/NonBlankStringPlumatic)
+   dn                      :- su/NonBlankString
+   uid                     :- (s/maybe su/NonBlankString)
    {:keys [group-base]}    :- i/LDAPSettings
-   group-membership-filter :- su/NonBlankStringPlumatic]
+   group-membership-filter :- su/NonBlankString]
   (when group-base
     (let [results (ldap/search
                    ldap-connection
@@ -65,13 +65,13 @@
 (s/defn ldap-search-result->user-info :- (s/maybe i/UserInfo)
   "Convert the result "
   [ldap-connection               :- LDAPConnectionPool
-   {:keys [dn uid], :as result}  :- su/MapPlumatic
+   {:keys [dn uid], :as result}  :- su/Map
    {:keys [first-name-attribute
            last-name-attribute
            email-attribute
            sync-groups?]
     :as   settings}              :- i/LDAPSettings
-   group-membership-filter       :- su/NonBlankStringPlumatic]
+   group-membership-filter       :- su/NonBlankString]
   (let [{first-name (keyword first-name-attribute)
          last-name  (keyword last-name-attribute)
          email      (keyword email-attribute)} result]
@@ -90,7 +90,7 @@
   "Get user information for the supplied username."
   metabase-enterprise.enhancements.integrations.ldap
   [ldap-connection :- LDAPConnectionPool
-   username        :- su/NonBlankStringPlumatic
+   username        :- su/NonBlankString
    settings        :- i/LDAPSettings]
   (when-let [result (search ldap-connection username settings)]
     (ldap-search-result->user-info ldap-connection result settings group-membership-filter)))
@@ -98,9 +98,9 @@
 
 ;;; --------------------------------------------- fetch-or-create-user! ----------------------------------------------
 
-(s/defn ldap-groups->mb-group-ids :- #{su/IntGreaterThanZeroPlumatic}
+(s/defn ldap-groups->mb-group-ids :- #{su/IntGreaterThanZero}
   "Translate a set of a user's group DNs to a set of MB group IDs using the configured mappings."
-  [ldap-groups              :- (s/maybe [su/NonBlankStringPlumatic])
+  [ldap-groups              :- (s/maybe [su/NonBlankString])
    {:keys [group-mappings]} :- (select-keys i/LDAPSettings [:group-mappings s/Keyword])]
   (-> group-mappings
       (select-keys (map #(DN. (str %)) ldap-groups))
@@ -108,7 +108,7 @@
       flatten
       set))
 
-(s/defn all-mapped-group-ids :- #{su/IntGreaterThanZeroPlumatic}
+(s/defn all-mapped-group-ids :- #{su/IntGreaterThanZero}
   "Returns the set of all MB group IDs that have configured mappings."
   [{:keys [group-mappings]} :- (select-keys i/LDAPSettings [:group-mappings s/Keyword])]
   (-> group-mappings
diff --git a/src/metabase/integrations/ldap/interface.clj b/src/metabase/integrations/ldap/interface.clj
index 69f29bf1be0def8acd27fcdc66a6f82d8f033029..042b51275ec9962ca41a4ddecdd5224c7a7caadf 100644
--- a/src/metabase/integrations/ldap/interface.clj
+++ b/src/metabase/integrations/ldap/interface.clj
@@ -15,23 +15,23 @@
 
 (def UserInfo
   "Schema for LDAP User info as returned by `user-info` and used as input to `fetch-or-create-user!`."
-  {:dn         su/NonBlankStringPlumatic
-   :first-name (s/maybe su/NonBlankStringPlumatic)
-   :last-name  (s/maybe su/NonBlankStringPlumatic)
-   :email      su/EmailPlumatic
-   :groups     [su/NonBlankStringPlumatic]
+  {:dn         su/NonBlankString
+   :first-name (s/maybe su/NonBlankString)
+   :last-name  (s/maybe su/NonBlankString)
+   :email      su/Email
+   :groups     [su/NonBlankString]
    s/Keyword   s/Any})
 
 (def LDAPSettings
   "Options passed to LDAP integration implementations. These are just the various LDAP Settings from
   `metabase.integrations.ldap`, packaged up as a single map so implementations don't need to fetch Setting values
   directly."
-  {:first-name-attribute su/NonBlankStringPlumatic
-   :last-name-attribute  su/NonBlankStringPlumatic
-   :email-attribute      su/NonBlankStringPlumatic
+  {:first-name-attribute su/NonBlankString
+   :last-name-attribute  su/NonBlankString
+   :email-attribute      su/NonBlankString
    :sync-groups?         s/Bool
-   :user-base            su/NonBlankStringPlumatic
-   :user-filter          su/NonBlankStringPlumatic
-   :group-base           (s/maybe su/NonBlankStringPlumatic)
-   :group-mappings       (s/maybe {DN [su/IntGreaterThanZeroPlumatic]})
+   :user-base            su/NonBlankString
+   :user-filter          su/NonBlankString
+   :group-base           (s/maybe su/NonBlankString)
+   :group-mappings       (s/maybe {DN [su/IntGreaterThanZero]})
    s/Keyword             s/Any})
diff --git a/src/metabase/integrations/slack.clj b/src/metabase/integrations/slack.clj
index c257100a82e7e1fe8503e9368e74bae86b11312f..f2892f2f0502013e4c2e20cda64cde674a75f677 100644
--- a/src/metabase/integrations/slack.clj
+++ b/src/metabase/integrations/slack.clj
@@ -199,7 +199,7 @@
 
 (s/defn valid-token?
   "Check whether a Slack token is valid by checking if the `conversations.list` Slack api accepts it."
-  [token :- su/NonBlankStringPlumatic]
+  [token :- su/NonBlankString]
   (try
     (binding [*send-token-error-emails?* false]
       (boolean (take 1 (:channels (GET "conversations.list" :limit 1, :token token)))))
@@ -286,7 +286,7 @@
 (s/defn join-channel!
   "Given a channel ID, calls Slack API `conversations.join` endpoint to join the channel as the Metabase Slack app.
   This must be done before uploading a file to the channel, if using a Slack app integration."
-  [channel-id :- su/NonBlankStringPlumatic]
+  [channel-id :- su/NonBlankString]
   (POST "conversations.join" {:form-params {:channel channel-id}}))
 
 (defn- maybe-lookup-id
@@ -303,7 +303,7 @@
 
 (s/defn upload-file!
   "Calls Slack API `files.upload` endpoint and returns the URL of the uploaded file."
-  [file :- NonEmptyByteArray, filename :- su/NonBlankStringPlumatic, channel-id :- su/NonBlankStringPlumatic]
+  [file :- NonEmptyByteArray, filename :- su/NonBlankString, channel-id :- su/NonBlankString]
   {:pre [(slack-configured?)]}
   (let [request  {:multipart [{:name "file",     :content file}
                               {:name "filename", :content filename}
@@ -325,7 +325,7 @@
 (s/defn post-chat-message!
   "Calls Slack API `chat.postMessage` endpoint and posts a message to a channel. `attachments` should be serialized
   JSON."
-  [channel-id :- su/NonBlankStringPlumatic, text-or-nil :- (s/maybe s/Str) & [attachments]]
+  [channel-id :- su/NonBlankString, text-or-nil :- (s/maybe s/Str) & [attachments]]
   ;; TODO: it would be nice to have an emoji or icon image to use here
   (POST "chat.postMessage"
         {:form-params
diff --git a/src/metabase/models/bookmark.clj b/src/metabase/models/bookmark.clj
index 39721f170acc2cff79f47ceb690fb8c4a5e9fcf2..15f8cf42eddb0f5cb01ad725525b30a06b75dbc0 100644
--- a/src/metabase/models/bookmark.clj
+++ b/src/metabase/models/bookmark.clj
@@ -26,8 +26,8 @@
   although the compound key can be inferred from it."
   {:id                               s/Str
    :type                             (s/enum "card" "collection" "dashboard")
-   :item_id                          su/IntGreaterThanZeroPlumatic
-   :name                             su/NonBlankStringPlumatic
+   :item_id                          su/IntGreaterThanZero
+   :name                             su/NonBlankString
    (s/optional-key :dataset)         (s/maybe s/Bool)
    (s/optional-key :display)         (s/maybe s/Str)
    (s/optional-key :authority_level) (s/maybe s/Str)
diff --git a/src/metabase/models/collection.clj b/src/metabase/models/collection.clj
index 83f0bf39e33268a2c74667d1f7dfb3c44511c3cc..7293ee6501fff16425da05d02321823ec5a44301 100644
--- a/src/metabase/models/collection.clj
+++ b/src/metabase/models/collection.clj
@@ -118,7 +118,7 @@
   "Build a 'location path' from a sequence of `collections-or-ids`.
 
      (location-path 10 20) ; -> \"/10/20/\""
-  [& collections-or-ids :- [(s/cond-pre su/IntGreaterThanZeroPlumatic su/MapPlumatic)]]
+  [& collections-or-ids :- [(s/cond-pre su/IntGreaterThanZero su/Map)]]
   (if-not (seq collections-or-ids)
     "/"
     (str
@@ -127,14 +127,14 @@
                      (u/the-id collection-or-id)))
      "/")))
 
-(s/defn location-path->ids :- [su/IntGreaterThanZeroPlumatic]
+(s/defn location-path->ids :- [su/IntGreaterThanZero]
   "'Explode' a `location-path` into a sequence of Collection IDs, and parse them as integers.
 
      (location-path->ids \"/10/20/\") ; -> [10 20]"
   [location-path :- LocationPath]
   (unchecked-location-path->ids location-path))
 
-(s/defn location-path->parent-id :- (s/maybe su/IntGreaterThanZeroPlumatic)
+(s/defn location-path->parent-id :- (s/maybe su/IntGreaterThanZero)
   "Given a `location-path` fetch the ID of the direct of a Collection.
 
      (location-path->parent-id \"/10/20/\") ; -> 20"
@@ -212,7 +212,7 @@
   (s/cond-pre
    RootCollection
    {:location LocationPath
-    :id       su/IntGreaterThanZeroPlumatic
+    :id       su/IntGreaterThanZero
     s/Keyword s/Any}))
 
 (s/defn ^:private parent :- CollectionWithLocationAndIDOrRoot
@@ -237,7 +237,7 @@
 (def VisibleCollections
   "Includes the possible values for visible collections, either `:all` or a set of ids, possibly including `\"root\"` to
   represent the root collection."
-  (s/cond-pre (s/eq :all) #{(s/cond-pre (s/eq "root") su/IntGreaterThanZeroPlumatic)}))
+  (s/cond-pre (s/eq :all) #{(s/cond-pre (s/eq "root") su/IntGreaterThanZero)}))
 
 (s/defn permissions-set->visible-collection-ids :- VisibleCollections
   "Given a `permissions-set` (presumably those of the current user), return a set of IDs of Collections that the
@@ -396,7 +396,7 @@
   [collection]
   (effective-ancestors* collection))
 
-(s/defn ^:private parent-id* :- (s/maybe su/IntGreaterThanZeroPlumatic)
+(s/defn ^:private parent-id* :- (s/maybe su/IntGreaterThanZero)
   [{:keys [location]} :- CollectionWithLocationOrRoot]
   (some-> location location-path->parent-id))
 
@@ -467,7 +467,7 @@
         ;; key
         :children)))
 
-(s/defn descendant-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic})
+(s/defn descendant-ids :- (s/maybe #{su/IntGreaterThanZero})
   "Return a set of IDs of all descendant Collections of a `collection`."
   [collection :- CollectionWithLocationAndIDOrRoot]
   (db/select-ids Collection :location [:like (str (children-location collection) \%)]))
@@ -613,7 +613,7 @@
         :set    {:location (hsql/call :replace :location orig-children-location new-children-location)}
         :where  [:like :location (str orig-children-location "%")]}))))
 
-(s/defn ^:private collection->descendant-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic})
+(s/defn ^:private collection->descendant-ids :- (s/maybe #{su/IntGreaterThanZero})
   [collection :- CollectionWithLocationAndIDOrRoot, & additional-conditions]
   (apply db/select-ids Collection
          :location [:like (str (children-location collection) "%")]
@@ -656,7 +656,7 @@
   "Schema for a Collection instance that has a valid `:location`, and a `:personal_owner_id` key *present* (but not
   neccesarily non-nil)."
   {:location          LocationPath
-   :personal_owner_id (s/maybe su/IntGreaterThanZeroPlumatic)
+   :personal_owner_id (s/maybe su/IntGreaterThanZero)
    s/Keyword          s/Any})
 
 (s/defn is-personal-collection-or-descendant-of-one? :- s/Bool
@@ -730,7 +730,7 @@
 (s/defn ^:private check-changes-allowed-for-personal-collection
   "If we're trying to UPDATE a Personal Collection, make sure the proposed changes are allowed. Personal Collections
   have lots of restrictions -- you can't archive them, for example, nor can you transfer them to other Users."
-  [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/MapPlumatic]
+  [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/Map]
   ;; you're not allowed to change the `:personal_owner_id` of a Collection!
   ;; double-check and make sure it's not just the existing value getting passed back in for whatever reason
   (let [unchangeable {:personal_owner_id (tru "You are not allowed to change the owner of a Personal Collection.")
@@ -749,7 +749,7 @@
 
 (s/defn ^:private maybe-archive-or-unarchive!
   "If `:archived` specified in the updates map, archive/unarchive as needed."
-  [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/MapPlumatic]
+  [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/Map]
   ;; If the updates map contains a value for `:archived`, see if it's actually something different than current value
   (when (api/column-will-change? :archived collection-before-updates collection-updates)
     ;; check to make sure we're not trying to change location at the same time
@@ -1052,7 +1052,7 @@
 ;;; |                                              Personal Collections                                              |
 ;;; +----------------------------------------------------------------------------------------------------------------+
 
-(s/defn format-personal-collection-name :- su/NonBlankStringPlumatic
+(s/defn format-personal-collection-name :- su/NonBlankString
   "Constructs the personal collection name from user name.
   When displaying to users we'll tranlsate it to user's locale,
   but to keeps things consistent in the database, we'll store the name in site's locale.
@@ -1069,7 +1069,7 @@
       (and first-name last-name) (trs "{0} {1}''s Personal Collection" first-name last-name)
       :else                      (trs "{0}''s Personal Collection" (or first-name last-name email)))))
 
-(s/defn user->personal-collection-name :- su/NonBlankStringPlumatic
+(s/defn user->personal-collection-name :- su/NonBlankString
   "Come up with a nice name for the Personal Collection for `user-or-id`."
   [user-or-id user-or-site]
   (let [{first-name :first_name
diff --git a/src/metabase/models/collection/graph.clj b/src/metabase/models/collection/graph.clj
index cb7c255b630cec1e3ae79ec7700977841f9da175..94d9c9a20b5d4257789f64e934864c642be0247d 100644
--- a/src/metabase/models/collection/graph.clj
+++ b/src/metabase/models/collection/graph.clj
@@ -27,11 +27,11 @@
 (def ^:private GroupPermissionsGraph
   "collection-id -> status"
   {(s/optional-key :root) CollectionPermissions   ; when doing a delta between old graph and new graph root won't always
-   su/IntGreaterThanZeroPlumatic  CollectionPermissions}) ; be present, which is why it's *optional*
+   su/IntGreaterThanZero  CollectionPermissions}) ; be present, which is why it's *optional*
 
 (def ^:private PermissionsGraph
   {:revision s/Int
-   :groups   {su/IntGreaterThanZeroPlumatic GroupPermissionsGraph}})
+   :groups   {su/IntGreaterThanZero GroupPermissionsGraph}})
 
 
 ;;; -------------------------------------------------- Fetch Graph ---------------------------------------------------
@@ -55,10 +55,10 @@
    (for [collection-id collection-ids]
      {collection-id (perms-type-for-collection permissions-set collection-id)})))
 
-(s/defn ^:private non-personal-collection-ids :- #{su/IntGreaterThanZeroPlumatic}
+(s/defn ^:private non-personal-collection-ids :- #{su/IntGreaterThanZero}
   "Return a set of IDs of all Collections that are neither Personal Collections nor descendants of Personal
   Collections (i.e., things that you can set Permissions for, and that should go in the graph.)"
-  [collection-namespace :- (s/maybe su/KeywordOrStringPlumatic)]
+  [collection-namespace :- (s/maybe su/KeywordOrString)]
   (let [personal-collection-ids (db/select-ids Collection :personal_owner_id [:not= nil])
         honeysql-form           {:select [[:id :id]]
                                  :from   [Collection]
@@ -96,7 +96,7 @@
   ([]
    (graph nil))
 
-  ([collection-namespace :- (s/maybe su/KeywordOrStringPlumatic)]
+  ([collection-namespace :- (s/maybe su/KeywordOrString)]
    (db/transaction
      (-> collection-namespace
          non-personal-collection-ids
@@ -108,9 +108,9 @@
 (s/defn ^:private update-collection-permissions!
   "Update the permissions for group ID with `group-id` on collection with ID
   `collection-id` in the optional `collection-namespace` to `new-collection-perms`."
-  [collection-namespace :- (s/maybe su/KeywordOrStringPlumatic)
-   group-id             :- su/IntGreaterThanZeroPlumatic
-   collection-id        :- (s/cond-pre (s/eq :root) su/IntGreaterThanZeroPlumatic)
+  [collection-namespace :- (s/maybe su/KeywordOrString)
+   group-id             :- su/IntGreaterThanZero
+   collection-id        :- (s/cond-pre (s/eq :root) su/IntGreaterThanZero)
    new-collection-perms :- CollectionPermissions]
   (let [collection-id (if (= collection-id :root)
                         (assoc collection/root-collection :namespace collection-namespace)
@@ -123,8 +123,8 @@
       :none  nil)))
 
 (s/defn ^:private update-group-permissions!
-  [collection-namespace :- (s/maybe su/KeywordOrStringPlumatic)
-   group-id             :- su/IntGreaterThanZeroPlumatic
+  [collection-namespace :- (s/maybe su/KeywordOrString)
+   group-id             :- su/IntGreaterThanZero
    new-group-perms      :- GroupPermissionsGraph]
   (doseq [[collection-id new-perms] new-group-perms]
     (update-collection-permissions! collection-namespace group-id collection-id new-perms)))
@@ -136,7 +136,7 @@
   ([new-graph]
    (update-graph! nil new-graph))
 
-  ([collection-namespace :- (s/maybe su/KeywordOrStringPlumatic), new-graph :- PermissionsGraph]
+  ([collection-namespace :- (s/maybe su/KeywordOrString), new-graph :- PermissionsGraph]
    (let [old-graph          (graph collection-namespace)
          old-perms          (:groups old-graph)
          new-perms          (:groups new-graph)
diff --git a/src/metabase/models/dashboard.clj b/src/metabase/models/dashboard.clj
index 00f4bf8d23deb50de368f046d7faf15df5c4e781..b193d5b05925c01cb0ec34b3b843b4de2c14d54d 100644
--- a/src/metabase/models/dashboard.clj
+++ b/src/metabase/models/dashboard.clj
@@ -391,14 +391,14 @@
     dashboard))
 
 (def ^:private ParamWithMapping
-  {:name     su/NonBlankStringPlumatic
-   :id       su/NonBlankStringPlumatic
+  {:name     su/NonBlankString
+   :id       su/NonBlankString
    :mappings (s/maybe #{dashboard-card/ParamMapping})
    s/Keyword s/Any})
 
-(s/defn ^:private dashboard->resolved-params* :- (let [param-id su/NonBlankStringPlumatic]
+(s/defn ^:private dashboard->resolved-params* :- (let [param-id su/NonBlankString]
                                                    {param-id ParamWithMapping})
-  [dashboard :- {(s/optional-key :parameters) (s/maybe [su/MapPlumatic])
+  [dashboard :- {(s/optional-key :parameters) (s/maybe [su/Map])
                  s/Keyword                    s/Any}]
   (let [dashboard           (hydrate dashboard [:ordered_cards :card])
         param-key->mappings (apply
diff --git a/src/metabase/models/dashboard_card.clj b/src/metabase/models/dashboard_card.clj
index be295d7bbdd84cf8b4edf22014cb6777db5a1a3a..9d401ef4b75411c5fa62eb00528521fc048f6dd3 100644
--- a/src/metabase/models/dashboard_card.clj
+++ b/src/metabase/models/dashboard_card.clj
@@ -83,7 +83,7 @@
 
 (s/defn retrieve-dashboard-card
   "Fetch a single DashboardCard by its ID value."
-  [id :- su/IntGreaterThanZeroPlumatic]
+  [id :- su/IntGreaterThanZero]
   (-> (db/select-one DashboardCard :id id)
       (hydrate :series)))
 
@@ -118,8 +118,8 @@
    *  If an existing DashboardCardSeries has no corresponding ID in `card-ids`, it will be deleted.
    *  All cards will be updated with a `position` according to their place in the collection of `card-ids`"
   {:arglists '([dashboard-card card-ids])}
-  [{:keys [id]} :- {:id su/IntGreaterThanZeroPlumatic, s/Keyword s/Any}
-   card-ids     :- [su/IntGreaterThanZeroPlumatic]]
+  [{:keys [id]} :- {:id su/IntGreaterThanZero, s/Keyword s/Any}
+   card-ids     :- [su/IntGreaterThanZero]]
   ;; first off, just delete all series on the dashboard card (we add them again below)
   (db/delete! DashboardCardSeries :dashboardcard_id id)
   ;; now just insert all of the series that were given to us
@@ -130,12 +130,12 @@
       (db/insert-many! DashboardCardSeries cards))))
 
 (def ^:private DashboardCardUpdates
-  {:id                                      su/IntGreaterThanZeroPlumatic
-   (s/optional-key :action_id)              (s/maybe su/IntGreaterThanZeroPlumatic)
-   (s/optional-key :parameter_mappings)     (s/maybe [su/MapPlumatic])
-   (s/optional-key :visualization_settings) (s/maybe su/MapPlumatic)
+  {:id                                      su/IntGreaterThanZero
+   (s/optional-key :action_id)              (s/maybe su/IntGreaterThanZero)
+   (s/optional-key :parameter_mappings)     (s/maybe [su/Map])
+   (s/optional-key :visualization_settings) (s/maybe su/Map)
    ;; series is a sequence of IDs of additional cards after the first to include as "additional serieses"
-   (s/optional-key :series)                 (s/maybe [su/IntGreaterThanZeroPlumatic])
+   (s/optional-key :series)                 (s/maybe [su/IntGreaterThanZero])
    s/Keyword                                s/Any})
 
 (s/defn update-dashboard-card!
@@ -168,18 +168,18 @@
 
 (def ParamMapping
   "Schema for a parameter mapping as it would appear in the DashboardCard `:parameter_mappings` column."
-  {:parameter_id su/NonBlankStringPlumatic
+  {:parameter_id su/NonBlankString
    ;; TODO -- validate `:target` as well... breaks a few tests tho so those will have to be fixed
    #_:target       #_s/Any
    s/Keyword     s/Any})
 
 (def ^:private NewDashboardCard
-  {:dashboard_id                            su/IntGreaterThanZeroPlumatic
-   (s/optional-key :card_id)                (s/maybe su/IntGreaterThanZeroPlumatic)
-   (s/optional-key :action_id)              (s/maybe su/IntGreaterThanZeroPlumatic)
+  {:dashboard_id                            su/IntGreaterThanZero
+   (s/optional-key :card_id)                (s/maybe su/IntGreaterThanZero)
+   (s/optional-key :action_id)              (s/maybe su/IntGreaterThanZero)
    ;; TODO - use ParamMapping. Breaks too many tests right now tho
-   (s/optional-key :parameter_mappings)     (s/maybe [#_ParamMapping su/MapPlumatic])
-   (s/optional-key :visualization_settings) (s/maybe su/MapPlumatic)
+   (s/optional-key :parameter_mappings)     (s/maybe [#_ParamMapping su/Map])
+   (s/optional-key :visualization_settings) (s/maybe su/Map)
    ;; TODO - make the rest of the options explicit instead of just allowing whatever for other keys
    s/Keyword                                s/Any})
 
diff --git a/src/metabase/models/field_values.clj b/src/metabase/models/field_values.clj
index 61f2457e4167d39b2e2ac8ff5eff0a8b77006daa..06a0f5b5d2725bb00d7269c79b65e26c598b7862 100644
--- a/src/metabase/models/field_values.clj
+++ b/src/metabase/models/field_values.clj
@@ -82,7 +82,7 @@
 (models/defmodel FieldValues :metabase_fieldvalues)
 
 (defn- assert-valid-human-readable-values [{human-readable-values :human_readable_values}]
-  (when (s/check (s/maybe [(s/maybe su/NonBlankStringPlumatic)]) human-readable-values)
+  (when (s/check (s/maybe [(s/maybe su/NonBlankString)]) human-readable-values)
     (throw (ex-info (tru "Invalid human-readable-values: values must be a sequence; each item must be nil or a string")
                     {:human-readable-values human-readable-values
                      :status-code           400}))))
@@ -201,9 +201,9 @@
            visibility-type  :visibility_type
            has-field-values :has_field_values
            :as              field} field-or-field-id]
-      (s/check {:visibility_type  su/KeywordOrStringPlumatic
-                :base_type        (s/maybe su/KeywordOrStringPlumatic)
-                :has_field_values (s/maybe su/KeywordOrStringPlumatic)
+      (s/check {:visibility_type  su/KeywordOrString
+                :base_type        (s/maybe su/KeywordOrString)
+                :has_field_values (s/maybe su/KeywordOrString)
                 s/Keyword         s/Any}
                field)
       (boolean
diff --git a/src/metabase/models/moderation_review.clj b/src/metabase/models/moderation_review.clj
index 8c0ef1e923ea4e1092fe51719f3c57b0bab74b4d..17b21f4a41b296715194b8a358fc0136a0c34e6b 100644
--- a/src/metabase/models/moderation_review.clj
+++ b/src/metabase/models/moderation_review.clj
@@ -21,8 +21,8 @@
 ;; TODO: Appears to be unused, remove?
 (def ReviewChanges
   "Schema for a ModerationReview that's being updated (so most keys are optional)"
-  {(s/optional-key :id)                  su/IntGreaterThanZeroPlumatic
-   (s/optional-key :moderated_item_id)   su/IntGreaterThanZeroPlumatic
+  {(s/optional-key :id)                  su/IntGreaterThanZero
+   (s/optional-key :moderated_item_id)   su/IntGreaterThanZero
    (s/optional-key :moderated_item_type) moderation/moderated-item-types
    (s/optional-key :status)              Statuses
    (s/optional-key :text)                (s/maybe s/Str)
@@ -64,9 +64,9 @@
 (s/defn create-review!
   "Create a new ModerationReview"
   [params :-
-   {:moderated_item_id       su/IntGreaterThanZeroPlumatic
+   {:moderated_item_id       su/IntGreaterThanZero
     :moderated_item_type     moderation/moderated-item-types
-    :moderator_id            su/IntGreaterThanZeroPlumatic
+    :moderator_id            su/IntGreaterThanZero
     (s/optional-key :status) Statuses
     (s/optional-key :text)   (s/maybe s/Str)}]
   (db/transaction
diff --git a/src/metabase/models/params.clj b/src/metabase/models/params.clj
index 8a011c4c72462c225f75e29c2b43e978584c1d66..09b07f30b533e98849a9fcb77faa7fec7c505385 100644
--- a/src/metabase/models/params.clj
+++ b/src/metabase/models/params.clj
@@ -23,14 +23,14 @@
 (defn assert-valid-parameters
   "Receive a Paremeterized Object and check if its parameters is valid."
   [{:keys [parameters]}]
-  (when (s/check (s/maybe [su/ParameterPlumatic]) parameters)
+  (when (s/check (s/maybe [su/Parameter]) parameters)
     (throw (ex-info (tru ":parameters must be a sequence of maps with :id and :type keys")
                     {:parameters parameters}))))
 
 (defn assert-valid-parameter-mappings
   "Receive a Paremeterized Object and check if its parameters is valid."
   [{:keys [parameter_mappings]}]
-  (when (s/check (s/maybe [su/ParameterMappingPlumatic]) parameter_mappings)
+  (when (s/check (s/maybe [su/ParameterMapping]) parameter_mappings)
     (throw (ex-info (tru ":parameter_mappings must be a sequence of maps with :parameter_id and :type keys")
                     {:parameter_mappings parameter_mappings}))))
 
@@ -153,7 +153,7 @@
   "Get the Fields (as a map of Field ID -> Field) that shoudl be returned for hydrated `:param_fields` for a Card or
   Dashboard. These only contain the minimal amount of information necessary needed to power public or embedded
   parameter widgets."
-  [field-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic})]
+  [field-ids :- (s/maybe #{su/IntGreaterThanZero})]
   (when (seq field-ids)
     (m/index-by :id (-> (db/select Field:params-columns-only :id [:in field-ids])
                         (hydrate :has_field_values :name_field [:dimensions :human_readable_field])
@@ -198,7 +198,7 @@
    (for [{card :card} (:ordered_cards dashboard)]
      (card->template-tag-field-ids card))))
 
-(s/defn dashboard->param-field-ids :- #{su/IntGreaterThanZeroPlumatic}
+(s/defn dashboard->param-field-ids :- #{su/IntGreaterThanZero}
   "Return a set of Field IDs referenced by parameters in Cards in this `dashboard`, or `nil` if none are referenced. This
   also includes IDs of Fields that are to be found in the 'implicit' parameters for SQL template tag Field filters."
   [dashboard]
@@ -225,7 +225,7 @@
              :when                      field]
          field)))
 
-(s/defn card->template-tag-field-ids :- #{su/IntGreaterThanZeroPlumatic}
+(s/defn card->template-tag-field-ids :- #{su/IntGreaterThanZero}
   "Return a set of Field IDs referenced in template tag parameters in `card`. This is mostly used for determining
   Fields referenced by Cards for purposes other than processing queries. Filters out `:field` clauses using names."
   [card]
diff --git a/src/metabase/models/params/card_values.clj b/src/metabase/models/params/card_values.clj
index 350d088801e89bd754460de11ca4a501edd18c09..ba2b51a0f845956b0a63587d022c524c1851e5cc 100644
--- a/src/metabase/models/params/card_values.clj
+++ b/src/metabase/models/params/card_values.clj
@@ -43,9 +43,9 @@
   ([card-id value-field-ref]
    (values-from-card card-id value-field-ref nil))
 
-  ([card-id     :- su/IntGreaterThanZeroPlumatic
-    value-field :- su/FieldPlumatic
-    query       :- (s/maybe su/NonBlankStringPlumatic)]
+  ([card-id     :- su/IntGreaterThanZero
+    value-field :- su/Field
+    query       :- (s/maybe su/NonBlankString)]
    (let [mbql-query   (values-from-card-query card-id value-field query)
          query-limit  (get-in mbql-query [:query :limit])
          result       (qp/process-query mbql-query)]
diff --git a/src/metabase/models/params/chain_filter.clj b/src/metabase/models/params/chain_filter.clj
index 85bafaca608530c0eb4b8db7c3367022e25163e1..a6f437ea5de0f249cc4cb9c57bf032c0d3195ce9 100644
--- a/src/metabase/models/params/chain_filter.clj
+++ b/src/metabase/models/params/chain_filter.clj
@@ -355,19 +355,19 @@
 
 (def ^:private Options
   ;; if original-field-id is specified, we'll include this in the results. For Field->Field remapping.
-  {(s/optional-key :original-field-id) (s/maybe su/IntGreaterThanZeroPlumatic)
+  {(s/optional-key :original-field-id) (s/maybe su/IntGreaterThanZero)
    ;; return at most the lesser of `limit` (if specified) and `max-results`.
-   (s/optional-key :limit)             (s/maybe su/IntGreaterThanZeroPlumatic)})
+   (s/optional-key :limit)             (s/maybe su/IntGreaterThanZero)})
 
 (def ^:private max-results 1000)
 
 (def ^:private ConstraintsMap
   "Schema for map of (other) Field ID -> value for additional constraints for the `chain-filter` results."
-  {su/IntGreaterThanZeroPlumatic s/Any})
+  {su/IntGreaterThanZero s/Any})
 
 (s/defn ^:private chain-filter-mbql-query
   "Generate the MBQL query powering `chain-filter`."
-  [field-id                          :- su/IntGreaterThanZeroPlumatic
+  [field-id                          :- su/IntGreaterThanZero
    constraints                       :- (s/maybe ConstraintsMap)
    {:keys [original-field-id limit]} :- (s/maybe Options)]
   {:database (field/field-id->database-id field-id)
@@ -420,7 +420,7 @@
 
 (s/defn ^:private unremapped-chain-filter
   "Chain filtering without all the fancy remapping stuff on top of it."
-  [field-id                                 :- su/IntGreaterThanZeroPlumatic
+  [field-id                                 :- su/IntGreaterThanZero
    constraints                              :- (s/maybe ConstraintsMap)
    {:keys [original-field-id], :as options} :- (s/maybe Options)]
   (let [mbql-query (chain-filter-mbql-query field-id constraints options)]
@@ -467,7 +467,7 @@
   (su/non-empty {s/Any (s/maybe s/Str)}))
 
 (s/defn ^:private human-readable-remapping-map :- (s/maybe HumanReadableRemappingMap)
-  [field-id :- su/IntGreaterThanZeroPlumatic]
+  [field-id :- su/IntGreaterThanZero]
   (when-let [{orig :values, remapped :human_readable_values} (db/select-one [FieldValues :values :human_readable_values]
                                                                {:where [:and
                                                                         [:= :type "full"]
@@ -489,7 +489,7 @@
   "Chain filter, but for Fields that have human-readable values defined (e.g. you've went in and specified that enum
   value `1` should be displayed as `BIRD_TYPE_TOUCAN`). `v->human-readable` is a map of actual values in the
   database (e.g. `1`) to the human-readable version (`BIRD_TYPE_TOUCAN`)."
-  [field-id          :- su/IntGreaterThanZeroPlumatic
+  [field-id          :- su/IntGreaterThanZero
    v->human-readable :- HumanReadableRemappingMap
    constraints       :- (s/maybe ConstraintsMap)
    options           :- (s/maybe Options)]
@@ -499,8 +499,8 @@
 (s/defn ^:private field-to-field-remapped-chain-filter
   "Chain filter, but for Field->Field remappings (e.g. 'remap' `venue.category_id` -> `category.name`; search by
   `category.name` but return tuples of `[venue.category_id category.name]`."
-  [original-field-id :- su/IntGreaterThanZeroPlumatic
-   remapped-field-id :- su/IntGreaterThanZeroPlumatic
+  [original-field-id :- su/IntGreaterThanZero
+   remapped-field-id :- su/IntGreaterThanZero
    constraints       :- (s/maybe ConstraintsMap)
    options           :- (s/maybe Options)]
   (unremapped-chain-filter remapped-field-id constraints (assoc options :original-field-id original-field-id)))
@@ -512,10 +512,10 @@
   (hsql/call (u/qualified-name ::parens) x))
 
 ;; TODO -- add some caching here?
-(s/defn ^:private remapped-field-id :- (s/maybe su/IntGreaterThanZeroPlumatic)
+(s/defn ^:private remapped-field-id :- (s/maybe su/IntGreaterThanZero)
   "Efficient query to find the ID of the Field we're remapping `field-id` to, if it has either type of Field -> Field
   remapping."
-  [field-id :- su/IntGreaterThanZeroPlumatic]
+  [field-id :- su/IntGreaterThanZero]
   (let [[{:keys [id]}] (db/query {:select [[:ids.id :id]]
                                   :from   [[{:union [(parens
                                                       {:select [[:dimension.human_readable_field_id :id]]
@@ -572,7 +572,7 @@
     (chain-filter %venues.price {} :limit 10)
 
   For remapped columns, this returns results as a sequence of `[value remapped-value]` pairs."
-  [field-id    :- su/IntGreaterThanZeroPlumatic
+  [field-id    :- su/IntGreaterThanZero
    constraints :- (s/maybe ConstraintsMap)
    & options]
   (assert (even? (count options)))
@@ -606,9 +606,9 @@
                          :base-type   base-type}))))))
 
 (s/defn ^:private unremapped-chain-filter-search
-  [field-id    :- su/IntGreaterThanZeroPlumatic
+  [field-id    :- su/IntGreaterThanZero
    constraints :- (s/maybe ConstraintsMap)
-   query       :- su/NonBlankStringPlumatic
+   query       :- su/NonBlankString
    options     :- (s/maybe Options)]
   (check-valid-search-field field-id)
   (let [query-constraint {field-id [:contains query {:case-sensitive false}]}
@@ -626,10 +626,10 @@
   "Chain filter search, but for Fields that have human-readable values defined (e.g. you've went in and specified that
   enum value `1` should be displayed as `BIRD_TYPE_TOUCAN`). `v->human-readable` is a map of actual values in the
   database (e.g. `1`) to the human-readable version (`BIRD_TYPE_TOUCAN`)."
-  [field-id          :- su/IntGreaterThanZeroPlumatic
+  [field-id          :- su/IntGreaterThanZero
    v->human-readable :- HumanReadableRemappingMap
    constraints       :- (s/maybe ConstraintsMap)
-   query             :- su/NonBlankStringPlumatic
+   query             :- su/NonBlankString
    options           :- (s/maybe Options)]
   (or (when-let [unremapped-values (not-empty (matching-unremapped-values query v->human-readable))]
         (let [query-constraint  {field-id (set unremapped-values)}
@@ -669,10 +669,10 @@
 (s/defn ^:private field-to-field-remapped-chain-filter-search
   "Chain filter search, but for Field->Field remappings e.g. 'remap' `venue.category_id` -> `category.name`; search by
   `category.name` but return tuples of `[venue.category_id category.name]`."
-  [original-field-id :- su/IntGreaterThanZeroPlumatic
-   remapped-field-id :- su/IntGreaterThanZeroPlumatic
+  [original-field-id :- su/IntGreaterThanZero
+   remapped-field-id :- su/IntGreaterThanZero
    constraints       :- (s/maybe ConstraintsMap)
-   query             :- su/NonBlankStringPlumatic
+   query             :- su/NonBlankString
    options           :- (s/maybe Options)]
   (unremapped-chain-filter-search remapped-field-id constraints query
                                   (assoc options :original-field-id original-field-id)))
@@ -680,9 +680,9 @@
 (s/defn chain-filter-search
   "Convenience version of `chain-filter` that adds a constraint to only return values of Field with `field-id`
   containing String `query`. Powers the `search/:query` version of the chain filter endpoint."
-  [field-id          :- su/IntGreaterThanZeroPlumatic
+  [field-id          :- su/IntGreaterThanZero
    constraints       :- (s/maybe ConstraintsMap)
-   query             :- (s/maybe su/NonBlankStringPlumatic)
+   query             :- (s/maybe su/NonBlankString)
    & options]
   (assert (even? (count options)))
   (if (str/blank? query)
@@ -705,8 +705,8 @@
 
     ;; maybe we can't filter against Field 2 because there's no FK-> relationship
     (filterable-field-ids 1 #{2 3 4}) ; -> #{3 4}"
-  [field-id         :- su/IntGreaterThanZeroPlumatic
-   filter-field-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic})]
+  [field-id         :- su/IntGreaterThanZero
+   filter-field-ids :- (s/maybe #{su/IntGreaterThanZero})]
   (when (seq filter-field-ids)
     (let [mbql-query (chain-filter-mbql-query field-id
                                               (into {} (for [id filter-field-ids] [id nil]))
diff --git a/src/metabase/models/permissions.clj b/src/metabase/models/permissions.clj
index 5ccaa84c3c3350da00eca55fccaf695c70ca669e..30d9ab3e26ba5983e1451807eacfa1b2219033e0 100644
--- a/src/metabase/models/permissions.clj
+++ b/src/metabase/models/permissions.clj
@@ -373,7 +373,7 @@
 ;;; ------------------------------------------------- Path Util Fns --------------------------------------------------
 
 (def ^:private MapOrID
-  (s/cond-pre su/MapPlumatic su/IntGreaterThanZeroPlumatic))
+  (s/cond-pre su/Map su/IntGreaterThanZero))
 
 (s/defn data-perms-path :- Path
   "Return the [readwrite] permissions path for a Database, schema, or Table. (At the time of this writing, DBs and
@@ -579,8 +579,8 @@
   ([this read-or-write]
    (perms-objects-set-for-parent-collection nil this read-or-write))
 
-  ([collection-namespace :- (s/maybe su/KeywordOrStringPlumatic)
-    this                 :- {:collection_id (s/maybe su/IntGreaterThanZeroPlumatic) s/Keyword s/Any}
+  ([collection-namespace :- (s/maybe su/KeywordOrString)
+    this                 :- {:collection_id (s/maybe su/IntGreaterThanZero) s/Keyword s/Any}
     read-or-write        :- (s/enum :read :write)]
    ;; based on value of read-or-write determine the approprite function used to calculate the perms path
    (let [path-fn (case read-or-write
@@ -653,7 +653,7 @@
 (def ^:private SchemaPermissionsGraph
   (s/named
    (s/cond-pre (s/enum :none :all)
-               {su/IntGreaterThanZeroPlumatic TablePermissionsGraph})
+               {su/IntGreaterThanZero TablePermissionsGraph})
    "Valid perms graph for a schema"))
 
 (def ^:private NativePermissionsGraph
@@ -704,7 +704,7 @@
 (def ^:private DownloadSchemaPermissionsGraph
   (s/named
    (s/cond-pre (s/enum :full :limited :none)
-               {su/IntGreaterThanZeroPlumatic DownloadTablePermissionsGraph})
+               {su/IntGreaterThanZero DownloadTablePermissionsGraph})
    "Valid download perms graph for a schema"))
 
 (def ^:private DownloadNativePermissionsGraph
@@ -728,7 +728,7 @@
 (def ^:private DataModelSchemaPermissionsGraph
   (s/named
     (s/cond-pre (s/enum :all :none)
-                {su/IntGreaterThanZeroPlumatic DataModelTablePermissionsGraph})
+                {su/IntGreaterThanZero DataModelTablePermissionsGraph})
    "Valid data model perms graph for a schema"))
 
 (def DataModelPermissionsGraph
@@ -746,22 +746,22 @@
    "Valid details perms graph for a database"))
 
 (def ^:private StrictDBPermissionsGraph
-  {su/IntGreaterThanZeroPlumatic {(s/optional-key :data) StrictDataPermissionsGraph
+  {su/IntGreaterThanZero {(s/optional-key :data) StrictDataPermissionsGraph
                                   (s/optional-key :download) DownloadPermissionsGraph
                                   (s/optional-key :data-model) DataModelPermissionsGraph
                                   (s/optional-key :details) DetailsPermissions}})
 
 (def ^:private StrictPermissionsGraph
   {:revision s/Int
-   :groups   {su/IntGreaterThanZeroPlumatic StrictDBPermissionsGraph}})
+   :groups   {su/IntGreaterThanZero StrictDBPermissionsGraph}})
 
 (def ^:private ExecutionGroupPermissionsGraph
   (s/cond-pre ExecutePermissions
-              {su/IntGreaterThanZeroPlumatic ExecutePermissions}))
+              {su/IntGreaterThanZero ExecutePermissions}))
 
 (def ^:private ExecutionPermissionsGraph
   {:revision s/Int
-   :groups   {su/IntGreaterThanZeroPlumatic ExecutionGroupPermissionsGraph}})
+   :groups   {su/IntGreaterThanZero ExecutionGroupPermissionsGraph}})
 
 ;;; +----------------------------------------------------------------------------------------------------------------+
 ;;; |                                                  GRAPH FETCH                                                   |
@@ -848,7 +848,7 @@
   NOTE: This function is meant for internal usage in this namespace only; use one of the other functions like
   `revoke-data-perms!` elsewhere instead of calling this directly."
   {:style/indent 2}
-  [group-or-id :- (s/cond-pre su/MapPlumatic su/IntGreaterThanZeroPlumatic) path :- Path & other-conditions]
+  [group-or-id :- (s/cond-pre su/Map su/IntGreaterThanZero) path :- Path & other-conditions]
   (let [where {:where (apply list
                              :and
                              [:= :group_id (u/the-id group-or-id)]
@@ -1037,7 +1037,7 @@
   This lives in non-EE code because it needs to be called during sync, in case a new table was discovered or a
   table was deleted. This ensures that native download perms are always up to date, even on OSS instances, in case
   they are upgraded to EE."
-  [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic]
+  [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero]
   (let [permissions-set (download-permissions-set group-id)
         table-ids-and-schemas (db/select-id->field :schema 'Table :db_id db-id :active [:= true])
         native-perm-level (reduce (fn [lowest-seen-perm-level [table-id table-schema]]
@@ -1066,20 +1066,20 @@
       (grant-permissions! group-id (native-feature-perms-path :download native-perm-level db-id)))))
 
 (s/defn ^:private update-table-read-permissions!
-  [group-id       :- su/IntGreaterThanZeroPlumatic
-   db-id          :- su/IntGreaterThanZeroPlumatic
+  [group-id       :- su/IntGreaterThanZero
+   db-id          :- su/IntGreaterThanZero
    schema         :- s/Str
-   table-id       :- su/IntGreaterThanZeroPlumatic
+   table-id       :- su/IntGreaterThanZero
    new-read-perms :- (s/enum :all :none)]
   ((case new-read-perms
      :all  grant-permissions!
      :none revoke-data-perms!) group-id (table-read-path db-id schema table-id)))
 
 (s/defn ^:private update-table-query-permissions!
-  [group-id        :- su/IntGreaterThanZeroPlumatic
-   db-id           :- su/IntGreaterThanZeroPlumatic
+  [group-id        :- su/IntGreaterThanZero
+   db-id           :- su/IntGreaterThanZero
    schema          :- s/Str
-   table-id        :- su/IntGreaterThanZeroPlumatic
+   table-id        :- su/IntGreaterThanZero
    new-query-perms :- (s/enum :all :segmented :none)]
   (case new-query-perms
     :all       (grant-permissions! group-id (table-query-path           db-id schema table-id))
@@ -1087,10 +1087,10 @@
     :none      (revoke-data-perms! group-id (table-query-path           db-id schema table-id))))
 
 (s/defn ^:private update-table-data-access-permissions!
-  [group-id        :- su/IntGreaterThanZeroPlumatic
-   db-id           :- su/IntGreaterThanZeroPlumatic
+  [group-id        :- su/IntGreaterThanZero
+   db-id           :- su/IntGreaterThanZero
    schema          :- s/Str
-   table-id        :- su/IntGreaterThanZeroPlumatic
+   table-id        :- su/IntGreaterThanZero
    new-table-perms :- TablePermissionsGraph]
   (cond
     (= new-table-perms :all)
@@ -1110,8 +1110,8 @@
       (when new-query-perms (update-table-query-permissions! group-id db-id schema table-id new-query-perms)))))
 
 (s/defn ^:private update-schema-data-access-permissions!
-  [group-id         :- su/IntGreaterThanZeroPlumatic
-   db-id            :- su/IntGreaterThanZeroPlumatic
+  [group-id         :- su/IntGreaterThanZero
+   db-id            :- su/IntGreaterThanZero
    schema           :- s/Str
    new-schema-perms :- SchemaPermissionsGraph]
   (cond
@@ -1122,7 +1122,7 @@
                                  (update-table-data-access-permissions! group-id db-id schema table-id table-perms))))
 
 (s/defn ^:private update-native-data-access-permissions!
-  [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-native-perms :- NativePermissionsGraph]
+  [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-native-perms :- NativePermissionsGraph]
   ;; revoke-native-permissions! will delete all entries that would give permissions for native access. Thus if you had
   ;; a root DB entry like `/db/11/` this will delete that too. In that case we want to create a new full schemas entry
   ;; so you don't lose access to all schemas when we modify native access.
@@ -1135,7 +1135,7 @@
     :none  nil))
 
 (s/defn ^:private update-db-data-access-permissions!
-  [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-db-perms :- StrictDataPermissionsGraph]
+  [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-db-perms :- StrictDataPermissionsGraph]
   (when-let [new-native-perms (:native new-db-perms)]
     (update-native-data-access-permissions! group-id db-id new-native-perms))
   (when-let [schemas (:schemas new-db-perms)]
@@ -1174,7 +1174,7 @@
     (throw (ee-permissions-exception perm-type))))
 
 (s/defn ^:private update-group-permissions!
-  [group-id :- su/IntGreaterThanZeroPlumatic new-group-perms :- StrictDBPermissionsGraph]
+  [group-id :- su/IntGreaterThanZero new-group-perms :- StrictDBPermissionsGraph]
   (doseq [[db-id new-db-perms] new-group-perms
           [perm-type new-perms] new-db-perms]
     (case perm-type
@@ -1202,7 +1202,7 @@
     (grant-permissions! group-id "/execute/")))
 
 (s/defn ^:private update-execution-permissions!
-  [group-id :- su/IntGreaterThanZeroPlumatic new-group-perms :- ExecutionGroupPermissionsGraph]
+  [group-id :- su/IntGreaterThanZero new-group-perms :- ExecutionGroupPermissionsGraph]
   (if (map? new-group-perms)
     (doseq [[db-id new-db-perms] new-group-perms]
       (update-feature-level-permission! group-id db-id new-db-perms :execute))
diff --git a/src/metabase/models/persisted_info.clj b/src/metabase/models/persisted_info.clj
index 363ce2e1ca7cee901dc0cb60580b7717247e7517..e012d7c5e6fccc950c1b3fea5f4f412727d2b5fd 100644
--- a/src/metabase/models/persisted_info.clj
+++ b/src/metabase/models/persisted_info.clj
@@ -25,8 +25,8 @@
 
 (def Definition
   "Definition spec for a cached table."
-  {:table-name su/NonBlankStringPlumatic
-   :field-definitions [{:field-name su/NonBlankStringPlumatic
+  {:table-name su/NonBlankString
+   :field-definitions [{:field-name su/NonBlankString
                         ;; TODO check (isa? :type/Integer :type/*)
                         :base-type  s/Keyword}]})
 
diff --git a/src/metabase/models/pulse.clj b/src/metabase/models/pulse.clj
index 1d3bc177ba29bcc2c5b71efb8645f128748920e6..866c24265f3b2ef18c5f352ca501bdc53cd69d9d 100644
--- a/src/metabase/models/pulse.clj
+++ b/src/metabase/models/pulse.clj
@@ -47,7 +47,7 @@
 (derive Pulse ::mi/read-policy.full-perms-for-perms-set)
 
 (defn- assert-valid-parameters [{:keys [parameters]}]
-  (when (s/check (s/maybe [{:id su/NonBlankStringPlumatic, s/Keyword s/Any}]) parameters)
+  (when (s/check (s/maybe [{:id su/NonBlankString, s/Keyword s/Any}]) parameters)
     (throw (ex-info (tru ":parameters must be a sequence of maps with String :id keys")
                     {:parameters parameters}))))
 
@@ -164,10 +164,10 @@
 (def CardRef
   "Schema for the map we use to internally represent the fact that a Card is in a Notification and the details about its
   presence there."
-  (su/with-api-error-message {:id                                 su/IntGreaterThanZeroPlumatic
+  (su/with-api-error-message {:id                                 su/IntGreaterThanZero
                               :include_csv                        s/Bool
                               :include_xls                        s/Bool
-                              (s/optional-key :dashboard_card_id) (s/maybe su/IntGreaterThanZeroPlumatic)}
+                              (s/optional-key :dashboard_card_id) (s/maybe su/IntGreaterThanZero)}
     (deferred-tru "value must be a map with the keys `{0}`, `{1}`, `{2}`, and `{3}`." "id" "include_csv" "include_xls" "dashboard_card_id")))
 
 (def HybridPulseCard
@@ -178,10 +178,10 @@
     (merge (:schema CardRef)
            {:name               (s/maybe s/Str)
             :description        (s/maybe s/Str)
-            :display            (s/maybe su/KeywordOrStringPlumatic)
-            :collection_id      (s/maybe su/IntGreaterThanZeroPlumatic)
-            :dashboard_id       (s/maybe su/IntGreaterThanZeroPlumatic)
-            :parameter_mappings (s/maybe [su/MapPlumatic])})
+            :display            (s/maybe su/KeywordOrString)
+            :collection_id      (s/maybe su/IntGreaterThanZero)
+            :dashboard_id       (s/maybe su/IntGreaterThanZero)
+            :parameter_mappings (s/maybe [su/Map])})
     (deferred-tru "value must be a map with the following keys `({0})`"
       (str/join ", " ["collection_id" "description" "display" "id" "include_csv" "include_xls" "name"
                       "dashboard_id" "parameter_mappings"]))))
@@ -381,7 +381,7 @@
 
 (s/defn card->ref :- CardRef
   "Create a card reference from a card or id"
-  [card :- su/MapPlumatic]
+  [card :- su/Map]
   {:id                (u/the-id card)
    :include_csv       (get card :include_csv false)
    :include_xls       (get card :include_xls false)
@@ -445,7 +445,7 @@
    * If an existing `PulseChannel` has no corresponding entry in `channels`, it will be deleted.
 
    * All previously existing channels will be updated with their most recent information."
-  [notification-or-id channels :- [su/MapPlumatic]]
+  [notification-or-id channels :- [su/Map]]
   (let [new-channels   (group-by (comp keyword :channel_type) channels)
         old-channels   (group-by (comp keyword :channel_type) (db/select PulseChannel
                                                                 :pulse_id (u/the-id notification-or-id)))
@@ -479,13 +479,13 @@
   {:style/indent 2}
   [cards    :- [{s/Keyword s/Any}]
    channels :- [{s/Keyword s/Any}]
-   kvs      :- {:name                                 su/NonBlankStringPlumatic
-                :creator_id                           su/IntGreaterThanZeroPlumatic
+   kvs      :- {:name                                 su/NonBlankString
+                :creator_id                           su/IntGreaterThanZero
                 (s/optional-key :skip_if_empty)       (s/maybe s/Bool)
-                (s/optional-key :collection_id)       (s/maybe su/IntGreaterThanZeroPlumatic)
-                (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZeroPlumatic)
-                (s/optional-key :dashboard_id)        (s/maybe su/IntGreaterThanZeroPlumatic)
-                (s/optional-key :parameters)          [su/MapPlumatic]}]
+                (s/optional-key :collection_id)       (s/maybe su/IntGreaterThanZero)
+                (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZero)
+                (s/optional-key :dashboard_id)        (s/maybe su/IntGreaterThanZero)
+                (s/optional-key :parameters)          [su/Map]}]
   (let [pulse-id (create-notification-and-add-cards-and-channels! kvs cards channels)]
     ;; return the full Pulse (and record our create event)
     (events/publish-event! :pulse-create (retrieve-pulse pulse-id))))
@@ -516,18 +516,18 @@
 
 (s/defn update-notification!
   "Update the supplied keys in a `notification`."
-  [notification :- {:id                                   su/IntGreaterThanZeroPlumatic
-                    (s/optional-key :name)                su/NonBlankStringPlumatic
+  [notification :- {:id                                   su/IntGreaterThanZero
+                    (s/optional-key :name)                su/NonBlankString
                     (s/optional-key :alert_condition)     AlertConditions
                     (s/optional-key :alert_above_goal)    s/Bool
                     (s/optional-key :alert_first_only)    s/Bool
                     (s/optional-key :skip_if_empty)       s/Bool
-                    (s/optional-key :collection_id)       (s/maybe su/IntGreaterThanZeroPlumatic)
-                    (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZeroPlumatic)
+                    (s/optional-key :collection_id)       (s/maybe su/IntGreaterThanZero)
+                    (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZero)
                     (s/optional-key :cards)               [CoercibleToCardRef]
-                    (s/optional-key :channels)            [su/MapPlumatic]
+                    (s/optional-key :channels)            [su/Map]
                     (s/optional-key :archived)            s/Bool
-                    (s/optional-key :parameters)          [su/MapPlumatic]}]
+                    (s/optional-key :parameters)          [su/Map]}]
   (db/update! Pulse (u/the-id notification)
     (u/select-keys-when notification
       :present [:collection_id :collection_position :archived]
diff --git a/src/metabase/models/pulse_card.clj b/src/metabase/models/pulse_card.clj
index 9b058be520a13810c3733f50d5d0b5042b7f7b86..1fbf750ce32de448100e9d4750cab4a2598739e8 100644
--- a/src/metabase/models/pulse_card.clj
+++ b/src/metabase/models/pulse_card.clj
@@ -32,10 +32,10 @@
       (or 0)))
 
 (def ^:private NewPulseCard
-  {:card_id                      su/IntGreaterThanZeroPlumatic
-   :pulse_id                     su/IntGreaterThanZeroPlumatic
-   :dashboard_card_id            su/IntGreaterThanZeroPlumatic
-   (s/optional-key :position)    (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)
+  {:card_id                      su/IntGreaterThanZero
+   :pulse_id                     su/IntGreaterThanZero
+   :dashboard_card_id            su/IntGreaterThanZero
+   (s/optional-key :position)    (s/maybe su/IntGreaterThanOrEqualToZero)
    (s/optional-key :include_csv) (s/maybe s/Bool)
    (s/optional-key :include_xls) (s/maybe s/Bool)})
 
diff --git a/src/metabase/models/query/permissions.clj b/src/metabase/models/query/permissions.clj
index 4247f139ffc5a950ca4df5ea84e4b35a3abf0062..2a527b5b136ab85dbfb705f5e0f52ebcbf7618ce 100644
--- a/src/metabase/models/query/permissions.clj
+++ b/src/metabase/models/query/permissions.clj
@@ -40,7 +40,7 @@
 ;; `table-segmented-query-path`. `perms-set` will require full access to the tables, `segmented-perms-set` will only
 ;; require segmented access
 
-(s/defn query->source-table-ids :- #{(s/cond-pre (s/eq ::native) su/IntGreaterThanZeroPlumatic)}
+(s/defn query->source-table-ids :- #{(s/cond-pre (s/eq ::native) su/IntGreaterThanZero)}
   "Return a sequence of all Table IDs referenced by `query`."
   [query]
   (set
@@ -67,7 +67,7 @@
 (def ^:private TableOrIDOrNativePlaceholder
   (s/cond-pre
    (s/eq ::native)
-   su/IntGreaterThanZeroPlumatic))
+   su/IntGreaterThanZero))
 
 (s/defn tables->permissions-path-set :- #{perms/Path}
   "Given a sequence of `tables-or-ids` referenced by a query, return a set of required permissions. A truthy value for
@@ -75,7 +75,7 @@
 
   Custom `table-perms-fn` and `native-perms-fn` can be passed as options to generate permissions paths for feature-level
   permissions, such as download permissions."
-  [database-or-id            :- (s/cond-pre su/IntGreaterThanZeroPlumatic su/MapPlumatic)
+  [database-or-id            :- (s/cond-pre su/IntGreaterThanZero su/Map)
    tables-or-ids             :- #{TableOrIDOrNativePlaceholder}
    {:keys [segmented-perms?
            table-perms-fn
@@ -103,7 +103,7 @@
 (s/defn ^:private source-card-read-perms :- #{perms/Path}
   "Calculate the permissions needed to run an ad-hoc query that uses a Card with `source-card-id` as its source
   query."
-  [source-card-id :- su/IntGreaterThanZeroPlumatic]
+  [source-card-id :- su/IntGreaterThanZero]
   (mi/perms-objects-set (or (db/select-one ['Card :collection_id] :id source-card-id)
                            (throw (Exception. (tru "Card {0} does not exist." source-card-id))))
                        :read))
@@ -122,7 +122,7 @@
   things when a single Card is busted (e.g. API endpoints that filter out unreadable Cards) and instead returns 'only
   admins can see this' permissions -- `#{\"db/0\"}` (DB 0 will never exist, thus normal users will never be able to
   get permissions for it, but admins have root perms and will still get to see (and hopefully fix) it)."
-  [query :- {:query su/MapPlumatic, s/Keyword s/Any}
+  [query :- {:query su/Map, s/Keyword s/Any}
    {:keys [throw-exceptions? already-preprocessed?], :as perms-opts} :- PermsOptions]
   (try
     (let [query (mbql.normalize/normalize query)]
diff --git a/src/metabase/models/revision/last_edit.clj b/src/metabase/models/revision/last_edit.clj
index bbeace2b7f196186e9460235684df7b7c46afdb3..6173c363186ae7e177584c5eefaf272f4c28fc45 100644
--- a/src/metabase/models/revision/last_edit.clj
+++ b/src/metabase/models/revision/last_edit.clj
@@ -22,7 +22,7 @@
 (def LastEditInfo
   "Schema of the `:last-edit-info` map. A subset of a user with a timestamp indicating when the last edit was."
   {:timestamp  (s/maybe s/Any)
-   :id         (s/maybe su/IntGreaterThanZeroPlumatic)
+   :id         (s/maybe su/IntGreaterThanZero)
    :first_name (s/maybe s/Str)
    :last_name  (s/maybe s/Str)
    :email      (s/maybe s/Str)})
diff --git a/src/metabase/models/task_history.clj b/src/metabase/models/task_history.clj
index 64b58e171181f13d5769cf29471c99206e44565d..4422801683d45a8213262cdee7c22ef275001407 100644
--- a/src/metabase/models/task_history.clj
+++ b/src/metabase/models/task_history.clj
@@ -71,8 +71,8 @@
 
 (s/defn all
   "Return all TaskHistory entries, applying `limit` and `offset` if not nil"
-  [limit  :- (s/maybe su/IntGreaterThanZeroPlumatic)
-   offset :- (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)]
+  [limit  :- (s/maybe su/IntGreaterThanZero)
+   offset :- (s/maybe su/IntGreaterThanOrEqualToZero)]
   (db/select TaskHistory (merge {:order-by [[:ended_at :desc]]}
                                 (when limit
                                   {:limit limit})
@@ -86,9 +86,9 @@
 
 (def ^:private TaskHistoryInfo
   "Schema for `info` passed to the `with-task-history` macro."
-  {:task                          su/NonBlankStringPlumatic  ; task name, i.e. `send-pulses`. Conventionally lisp-cased
+  {:task                          su/NonBlankString  ; task name, i.e. `send-pulses`. Conventionally lisp-cased
    (s/optional-key :db_id)        (s/maybe s/Int)    ; DB involved, for sync operations or other tasks where this is applicable.
-   (s/optional-key :task_details) (s/maybe su/MapPlumatic)}) ; additional map of details to include in the recorded row
+   (s/optional-key :task_details) (s/maybe su/Map)}) ; additional map of details to include in the recorded row
 
 (defn- save-task-history! [start-time-ms info]
   (let [end-time-ms (System/currentTimeMillis)
diff --git a/src/metabase/models/user.clj b/src/metabase/models/user.clj
index 93aa74beba3566f393527325da6b476a30195d9e..42eeb4168128c282a5f5abad994886f80747314e 100644
--- a/src/metabase/models/user.clj
+++ b/src/metabase/models/user.clj
@@ -174,7 +174,7 @@
 (def UserGroupMembership
   "Group Membership info of a User.
   In which :is_group_manager is only included if `advanced-permissions` is enabled."
-  {:id                                su/IntGreaterThanZeroPlumatic
+  {:id                                su/IntGreaterThanZero
    ;; is_group_manager only included if `advanced-permissions` is enabled
    (schema/optional-key :is_group_manager) schema/Bool})
 
@@ -273,23 +273,23 @@
 (def LoginAttributes
   "Login attributes, currently not collected for LDAP or Google Auth. Will ultimately be stored as JSON."
   (su/with-api-error-message
-    {su/KeywordOrStringPlumatic schema/Any}
+    {su/KeywordOrString schema/Any}
     (deferred-tru "login attribute keys must be a keyword or string")))
 
 (def NewUser
   "Required/optionals parameters needed to create a new user (for any backend)"
-  {(schema/optional-key :first_name)       (schema/maybe su/NonBlankStringPlumatic)
-   (schema/optional-key :last_name)        (schema/maybe su/NonBlankStringPlumatic)
-   :email                                  su/EmailPlumatic
-   (schema/optional-key :password)         (schema/maybe su/NonBlankStringPlumatic)
+  {(schema/optional-key :first_name)       (schema/maybe su/NonBlankString)
+   (schema/optional-key :last_name)        (schema/maybe su/NonBlankString)
+   :email                                  su/Email
+   (schema/optional-key :password)         (schema/maybe su/NonBlankString)
    (schema/optional-key :login_attributes) (schema/maybe LoginAttributes)
    (schema/optional-key :google_auth)      schema/Bool
    (schema/optional-key :ldap_auth)        schema/Bool})
 
 (def ^:private Invitor
   "Map with info about the admin creating the user, used in the new user notification code"
-  {:email      su/EmailPlumatic
-   :first_name (schema/maybe su/NonBlankStringPlumatic)
+  {:email      su/Email
+   :first_name (schema/maybe su/NonBlankString)
    schema/Any  schema/Any})
 
 (schema/defn ^:private insert-new-user!
diff --git a/src/metabase/public_settings/premium_features.clj b/src/metabase/public_settings/premium_features.clj
index 228e14b35a3e4da2e9c84f3eb75d298f71215868..69d071b8123162ad97b1b1261ef82dd99cdca099 100644
--- a/src/metabase/public_settings/premium_features.clj
+++ b/src/metabase/public_settings/premium_features.clj
@@ -57,11 +57,11 @@
 
 (def ^:private TokenStatus
   {:valid                               schema/Bool
-   :status                              su/NonBlankStringPlumatic
-   (schema/optional-key :error-details) (schema/maybe su/NonBlankStringPlumatic)
-   (schema/optional-key :features)      [su/NonBlankStringPlumatic]
+   :status                              su/NonBlankString
+   (schema/optional-key :error-details) (schema/maybe su/NonBlankString)
+   (schema/optional-key :features)      [su/NonBlankString]
    (schema/optional-key :trial)         schema/Bool
-   (schema/optional-key :valid_thru)    su/NonBlankStringPlumatic ; ISO 8601 timestamp
+   (schema/optional-key :valid_thru)    su/NonBlankString ; ISO 8601 timestamp
    ;; don't explode in the future if we add more to the response! lol
    schema/Any                           schema/Any})
 
@@ -113,7 +113,7 @@
    fetch-token-status*
    :ttl/threshold (* 1000 60 5)))
 
-(schema/defn ^:private valid-token->features* :- #{su/NonBlankStringPlumatic}
+(schema/defn ^:private valid-token->features* :- #{su/NonBlankString}
   [token :- ValidToken]
   (let [{:keys [valid status features error-details]} (fetch-token-status token)]
     ;; if token isn't valid throw an Exception with the `:status` message
@@ -170,7 +170,7 @@
                        (log/debug e (trs "Error validating token")))
                      ;; log every five minutes
                      :ttl/threshold (* 1000 60 5))]
-  (schema/defn ^:private token-features :- #{su/NonBlankStringPlumatic}
+  (schema/defn ^:private token-features :- #{su/NonBlankString}
     "Get the features associated with the system's premium features token."
     []
     (try
diff --git a/src/metabase/query_processor/card.clj b/src/metabase/query_processor/card.clj
index 3a4779dd9082a01ec4dfc166966b291393c40554..73b56594349612527dcbfb00e4d3000ca39c9f16 100644
--- a/src/metabase/query_processor/card.clj
+++ b/src/metabase/query_processor/card.clj
@@ -152,7 +152,7 @@
 (s/defn ^:private validate-card-parameters
   "Unless [[*allow-arbitrary-mbql-parameters*]] is truthy, check to make all supplied `parameters` actually match up
   with template tags in the query for Card with `card-id`."
-  [card-id :- su/IntGreaterThanZeroPlumatic parameters :- mbql.s/ParameterList]
+  [card-id :- su/IntGreaterThanZero parameters :- mbql.s/ParameterList]
   (when-not *allow-arbitrary-mbql-parameters*
     (let [template-tags (card-template-tag-parameters card-id)]
       (doseq [request-parameter parameters
diff --git a/src/metabase/query_processor/dashboard.clj b/src/metabase/query_processor/dashboard.clj
index e605ca9359bba8b9b84027417c350089f712b14b..77699438940b6f8aa72a5776241fbf5c06116532 100644
--- a/src/metabase/query_processor/dashboard.clj
+++ b/src/metabase/query_processor/dashboard.clj
@@ -111,14 +111,14 @@
                    target)))
    dashboard-param-id->param))
 
-(s/defn ^:private resolve-params-for-query :- (s/maybe [su/MapPlumatic])
+(s/defn ^:private resolve-params-for-query :- (s/maybe [su/Map])
   "Given a sequence of parameters included in a query-processing request to run the query for a Dashboard/Card, validate
   that those parameters exist and have allowed types, and merge in default values and other info from the parameter
   mappings."
-  [dashboard-id   :- su/IntGreaterThanZeroPlumatic
-   card-id        :- su/IntGreaterThanZeroPlumatic
-   dashcard-id    :- su/IntGreaterThanZeroPlumatic
-   request-params :- (s/maybe [su/MapPlumatic])]
+  [dashboard-id   :- su/IntGreaterThanZero
+   card-id        :- su/IntGreaterThanZero
+   dashcard-id    :- su/IntGreaterThanZero
+   request-params :- (s/maybe [su/Map])]
   (log/tracef "Resolving Dashboard %d Card %d query request parameters" dashboard-id card-id)
   (let [request-params            (mbql.normalize/normalize-fragment [:parameters] request-params)
         ;; ignore default values in request params as well. (#20516)
diff --git a/src/metabase/query_processor/middleware/add_dimension_projections.clj b/src/metabase/query_processor/middleware/add_dimension_projections.clj
index cfd298cc522b1c8cdef3c867db33296e2c8bb3d1..07c652e5819b10f6a86ce55648831d9aec1185f7 100644
--- a/src/metabase/query_processor/middleware/add_dimension_projections.clj
+++ b/src/metabase/query_processor/middleware/add_dimension_projections.clj
@@ -41,21 +41,21 @@
 
 (def ^:private ExternalRemappingDimensionInitialInfo
   "External remapping dimensions when they're first fetched from the app DB. We'll add extra info to this."
-  {:id                      su/IntGreaterThanZeroPlumatic   ; unique ID for the remapping
-   :name                    su/NonBlankStringPlumatic       ; display name for the remapping
-   :field_id                su/IntGreaterThanZeroPlumatic   ; ID of the Field being remapped
-   :human_readable_field_id su/IntGreaterThanZeroPlumatic}) ; ID of the FK Field to remap values to
+  {:id                      su/IntGreaterThanZero   ; unique ID for the remapping
+   :name                    su/NonBlankString       ; display name for the remapping
+   :field_id                su/IntGreaterThanZero   ; ID of the Field being remapped
+   :human_readable_field_id su/IntGreaterThanZero}) ; ID of the FK Field to remap values to
 
 (def ^:private ExternalRemappingDimension
   "Schema for the info we fetch about `external` type Dimensions that will be used for remappings in this Query. Fetched
   by the pre-processing portion of the middleware, and passed along to the post-processing portion."
   (assoc ExternalRemappingDimensionInitialInfo
-         :field_name                su/NonBlankStringPlumatic   ; Name of the Field being remapped
-         :human_readable_field_name su/NonBlankStringPlumatic)) ; Name of the FK field to remap values to
+         :field_name                su/NonBlankString   ; Name of the Field being remapped
+         :human_readable_field_name su/NonBlankString)) ; Name of the FK field to remap values to
 
 ;;;; Pre-processing
 
-(s/defn ^:private fields->field-id->remapping-dimension :- (s/maybe {su/IntGreaterThanZeroPlumatic ExternalRemappingDimensionInitialInfo})
+(s/defn ^:private fields->field-id->remapping-dimension :- (s/maybe {su/IntGreaterThanZero ExternalRemappingDimensionInitialInfo})
   "Given a sequence of field clauses (from the `:fields` clause), return a map of `:field-id` clause (other clauses
   are ineligable) to a remapping dimension information for any Fields that have an `external` type dimension remapping."
   [fields :- [mbql.s/Field]]
@@ -235,29 +235,29 @@
   {;; index of original column
    :col-index       s/Int
    ;; names
-   :from            su/NonBlankStringPlumatic
+   :from            su/NonBlankString
    ;; I'm not convinced this works if there's already a column with the same name in the results.
-   :to              su/NonBlankStringPlumatic
+   :to              su/NonBlankString
    ;; map of original value -> human readable value
-   :value->readable su/MapPlumatic
+   :value->readable su/Map
    ;; Info about the new column we will tack on to end of `:cols`
-   :new-column      su/MapPlumatic})
+   :new-column      su/Map})
 
 (def ^:private InternalColumnsInfo
   {:internal-only-dims (s/maybe [InternalDimensionInfo])
    ;; this is just (map :new-column internal-only-dims)
-   :internal-only-cols (s/maybe [su/MapPlumatic])})
+   :internal-only-cols (s/maybe [su/Map])})
 
 
 ;;;; Metadata
 
-(s/defn ^:private merge-metadata-for-internally-remapped-column :- [su/MapPlumatic]
+(s/defn ^:private merge-metadata-for-internally-remapped-column :- [su/Map]
   "If one of the internal remapped columns says it's remapped from this column, merge in the `:remapped_to` info."
-  [columns :- [su/MapPlumatic] {:keys [col-index to]} :- InternalDimensionInfo]
+  [columns :- [su/Map] {:keys [col-index to]} :- InternalDimensionInfo]
   (update (vec columns) col-index assoc :remapped_to to))
 
-(s/defn ^:private merge-metadata-for-internal-remaps :- [su/MapPlumatic]
-  [columns :- [su/MapPlumatic] {:keys [internal-only-dims]} :- (s/maybe InternalColumnsInfo)]
+(s/defn ^:private merge-metadata-for-internal-remaps :- [su/Map]
+  [columns :- [su/Map] {:keys [internal-only-dims]} :- (s/maybe InternalColumnsInfo)]
   (reduce
    merge-metadata-for-internally-remapped-column
    columns
@@ -286,7 +286,7 @@
 ;;     :options       {::new-field-dimension-id 1000}
 ;;     :name          "NAME"
 ;;     :display_name  "Sender ID"}
-(s/defn ^:private merge-metadata-for-externally-remapped-column* :- su/MapPlumatic
+(s/defn ^:private merge-metadata-for-externally-remapped-column* :- su/Map
   [columns
    {{::keys [original-field-dimension-id new-field-dimension-id]} :options
     :as                                          column}
@@ -330,25 +330,25 @@
     (when (not= column <>)
       (log/tracef "Added metadata:\n%s" (u/pprint-to-str 'green (second (data/diff column <>)))))))
 
-(s/defn ^:private merge-metadata-for-externally-remapped-column :- [su/MapPlumatic]
-  [columns :- [su/MapPlumatic] dimension :- ExternalRemappingDimension]
+(s/defn ^:private merge-metadata-for-externally-remapped-column :- [su/Map]
+  [columns :- [su/Map] dimension :- ExternalRemappingDimension]
   (log/tracef "Merging metadata for external dimension\n%s" (u/pprint-to-str 'yellow (into {} dimension)))
   (mapv #(merge-metadata-for-externally-remapped-column* columns % dimension)
         columns))
 
-(s/defn ^:private merge-metadata-for-external-remaps :- [su/MapPlumatic]
-  [columns :- [su/MapPlumatic] remapping-dimensions :- (s/maybe [ExternalRemappingDimension])]
+(s/defn ^:private merge-metadata-for-external-remaps :- [su/Map]
+  [columns :- [su/Map] remapping-dimensions :- (s/maybe [ExternalRemappingDimension])]
   (reduce
    merge-metadata-for-externally-remapped-column
    columns
    remapping-dimensions))
 
-(s/defn ^:private add-remapping-info :- [su/MapPlumatic]
+(s/defn ^:private add-remapping-info :- [su/Map]
   "Add `:display_name`, `:remapped_to`, and `:remapped_from` keys to columns for the results, needed by the frontend.
   To get this critical information, this uses the `remapping-dimensions` info saved by the pre-processing portion of
   this middleware for external remappings, and the internal-only remapped columns handled by post-processing
   middleware below for internal columns."
-  [columns              :- [su/MapPlumatic]
+  [columns              :- [su/Map]
    remapping-dimensions :- (s/maybe [ExternalRemappingDimension])
    internal-cols-info    :- (s/maybe InternalColumnsInfo)]
   (-> columns
diff --git a/src/metabase/query_processor/middleware/add_implicit_clauses.clj b/src/metabase/query_processor/middleware/add_implicit_clauses.clj
index e550acffba9b0a6db049b18e56d57d6a5db66e45..d1657ea32ed2ba91e7fd68a73db7c65941010477 100644
--- a/src/metabase/query_processor/middleware/add_implicit_clauses.clj
+++ b/src/metabase/query_processor/middleware/add_implicit_clauses.clj
@@ -42,7 +42,7 @@
 (s/defn sorted-implicit-fields-for-table :- mbql.s/Fields
   "For use when adding implicit Field IDs to a query. Return a sequence of field clauses, sorted by the rules listed
   in [[metabase.query-processor.sort]], for all the Fields in a given Table."
-  [table-id :- su/IntGreaterThanZeroPlumatic]
+  [table-id :- su/IntGreaterThanZero]
   (let [fields (table->sorted-fields table-id)]
     (when (empty? fields)
       (throw (ex-info (tru "No fields found for table {0}." (pr-str (:name (qp.store/table table-id))))
diff --git a/src/metabase/query_processor/middleware/annotate.clj b/src/metabase/query_processor/middleware/annotate.clj
index 43ad2a764b647da85d9bd452a9598c0d2b26a4ef..55a2e857be74028fc6ac8e874ef79da758afc815 100644
--- a/src/metabase/query_processor/middleware/annotate.clj
+++ b/src/metabase/query_processor/middleware/annotate.clj
@@ -29,7 +29,7 @@
   {:name                           s/Str
    :display_name                   s/Str
    ;; type of the Field. For Native queries we look at the values in the first 100 rows to make an educated guess
-   :base_type                      su/FieldTypePlumatic
+   :base_type                      su/FieldType
    ;; effective_type, coercion, etc don't go here. probably best to rename base_type to effective type in the return
    ;; from the metadata but that's for another day
    ;; where this column came from in the original query.
@@ -100,7 +100,7 @@
 ;;; +----------------------------------------------------------------------------------------------------------------+
 
 (s/defn ^:private join-with-alias :- (s/maybe mbql.s/Join)
-  [{:keys [joins source-query]} :- su/MapPlumatic, join-alias :- su/NonBlankStringPlumatic]
+  [{:keys [joins source-query]} :- su/Map, join-alias :- su/NonBlankString]
   (or (some
        (fn [{:keys [alias], :as join}]
          (when (= alias join-alias)
@@ -292,7 +292,7 @@
 
 (s/defn ^:private col-info-for-field-clause :- {:field_ref mbql.s/Field, s/Keyword s/Any}
   "Return results column metadata for a `:field` or `:expression` clause, in the format that gets returned by QP results"
-  [inner-query :- su/MapPlumatic, clause :- mbql.s/Field]
+  [inner-query :- su/Map, clause :- mbql.s/Field]
   (mbql.u/match-one clause
     :expression
     (col-info-for-expression inner-query &match)
@@ -326,7 +326,7 @@
     ;; otherwise for things like numbers just use that directly
     _ &match))
 
-(s/defn aggregation-name :- su/NonBlankStringPlumatic
+(s/defn aggregation-name :- su/NonBlankString
   "Return an appropriate aggregation name/alias *used inside a query* for an `:aggregation` subclause (an aggregation
   or expression). Takes an options map as schema won't support passing keypairs directly as a varargs.
 
@@ -365,7 +365,7 @@
 
 (declare aggregation-display-name)
 
-(s/defn ^:private aggregation-arg-display-name :- su/NonBlankStringPlumatic
+(s/defn ^:private aggregation-arg-display-name :- su/NonBlankString
   "Name to use for an aggregation clause argument such as a Field when constructing the complete aggregation name."
   [inner-query, ag-arg :- Object]
   (or (when (mbql.preds/Field? ag-arg)
@@ -373,7 +373,7 @@
           (some info [:display_name :name])))
       (aggregation-display-name inner-query ag-arg)))
 
-(s/defn aggregation-display-name :- su/NonBlankStringPlumatic
+(s/defn aggregation-display-name :- su/NonBlankString
   "Return an appropriate user-facing display name for an aggregation clause."
   [inner-query ag-clause]
   (mbql.u/match-one ag-clause
@@ -424,7 +424,7 @@
   "Return appropriate column metadata for an `:aggregation` clause."
   ;; `clause` is normally an aggregation clause but this function can call itself recursively; see comments by the
   ;; `match` pattern for field clauses below
-  [inner-query :- su/MapPlumatic, clause]
+  [inner-query :- su/Map, clause]
   (mbql.u/match-one clause
     ;; ok, if this is a aggregation w/ options recurse so we can get information about the ag it wraps
     [:aggregation-options ag _]
@@ -497,13 +497,13 @@
                    :actual   (:cols results)}))))))
 
 (s/defn ^:private cols-for-fields
-  [{:keys [fields], :as inner-query} :- su/MapPlumatic]
+  [{:keys [fields], :as inner-query} :- su/Map]
   (for [field fields]
     (assoc (col-info-for-field-clause inner-query field)
            :source :fields)))
 
 (s/defn ^:private cols-for-ags-and-breakouts
-  [{aggregations :aggregation, breakouts :breakout, :as inner-query} :- su/MapPlumatic]
+  [{aggregations :aggregation, breakouts :breakout, :as inner-query} :- su/Map]
   (concat
    (for [breakout breakouts]
      (assoc (col-info-for-field-clause inner-query breakout)
@@ -515,15 +515,15 @@
 
 (s/defn cols-for-mbql-query
   "Return results metadata about the expected columns in an 'inner' MBQL query."
-  [inner-query :- su/MapPlumatic]
+  [inner-query :- su/Map]
   (concat
    (cols-for-ags-and-breakouts inner-query)
    (cols-for-fields inner-query)))
 
 
 
-(s/defn ^:private merge-source-metadata-col :- (s/maybe su/MapPlumatic)
-  [source-metadata-col :- (s/maybe su/MapPlumatic) col :- (s/maybe su/MapPlumatic)]
+(s/defn ^:private merge-source-metadata-col :- (s/maybe su/Map)
+  [source-metadata-col :- (s/maybe su/Map) col :- (s/maybe su/Map)]
   (merge
     {} ;; ensure the type is not FieldInstance
     (when-let [field-id (:id source-metadata-col)]
diff --git a/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj b/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj
index a683296ca19a97447ef9d4a5077cbc990d7e0a48..1ce4659de9f6f0c89366b5950a75bd6036f51bf1 100644
--- a/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj
+++ b/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj
@@ -15,12 +15,12 @@
    [toucan.db :as db]))
 
 (def ^:private FieldTypeInfo
-  {:base-type                      (s/maybe su/FieldTypePlumatic)
-   (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationTypePlumatic)
+  {:base-type                      (s/maybe su/FieldType)
+   (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationType)
    s/Keyword                       s/Any})
 
 (def ^:private FieldIDOrName->TypeInfo
-  {(s/cond-pre su/NonBlankStringPlumatic su/IntGreaterThanZeroPlumatic) (s/maybe FieldTypeInfo)})
+  {(s/cond-pre su/NonBlankString su/IntGreaterThanZero) (s/maybe FieldTypeInfo)})
 
 ;; Unfortunately these Fields won't be in the store yet since Field resolution can't happen before we add the implicit
 ;; `:fields` clause, which happens after this
diff --git a/src/metabase/query_processor/middleware/auto_parse_filter_values.clj b/src/metabase/query_processor/middleware/auto_parse_filter_values.clj
index c6072d33b585680dd0eba1af603831debedf5e07..cb236ec617d1d846a487a59fe0d3c7aad6b20beb 100644
--- a/src/metabase/query_processor/middleware/auto_parse_filter_values.clj
+++ b/src/metabase/query_processor/middleware/auto_parse_filter_values.clj
@@ -12,7 +12,7 @@
    [metabase.util.schema :as su]
    [schema.core :as s]))
 
-(s/defn ^:private parse-value-for-base-type [v :- s/Str, base-type :- su/FieldTypePlumatic]
+(s/defn ^:private parse-value-for-base-type [v :- s/Str, base-type :- su/FieldType]
   {:pre [(string? v)]}
   (try
     (condp #(isa? %2 %1) base-type
diff --git a/src/metabase/query_processor/middleware/binning.clj b/src/metabase/query_processor/middleware/binning.clj
index 9ee49032b4734d6364d05a7f98d9473ba7e9767e..c32a3c3e8113834646bb787116e4c1b10ad20bd8 100644
--- a/src/metabase/query_processor/middleware/binning.clj
+++ b/src/metabase/query_processor/middleware/binning.clj
@@ -15,7 +15,7 @@
 
 ;;; ----------------------------------------------- Extracting Bounds ------------------------------------------------
 
-(def ^:private FieldID->Filters {su/IntGreaterThanZeroPlumatic [mbql.s/Filter]})
+(def ^:private FieldID->Filters {su/IntGreaterThanZero [mbql.s/Filter]})
 
 (s/defn ^:private filter->field-map :- FieldID->Filters
   "Find any comparison or `:between` filter and return a map of referenced Field ID -> all the clauses the reference
@@ -32,7 +32,7 @@
   "Given query criteria, find a min/max value for the binning strategy using the greatest user specified min value and
   the smallest user specified max value. When a user specified min or max is not found, use the global min/max for the
   given field."
-  [field-id :- (s/maybe su/IntGreaterThanZeroPlumatic), fingerprint :- (s/maybe su/MapPlumatic), field-id->filters :- FieldID->Filters]
+  [field-id :- (s/maybe su/IntGreaterThanZero), fingerprint :- (s/maybe su/Map), field-id->filters :- FieldID->Filters]
   (let [{global-min :min, global-max :max} (get-in fingerprint [:type :type/Number])
         filter-clauses                     (get field-id->filters field-id)
         ;; [:between <field> <min> <max>] or [:< <field> <x>]
@@ -58,11 +58,11 @@
 
 (s/defn ^:private calculate-bin-width :- s/Num
   "Calculate bin width required to cover interval [`min-value`, `max-value`] with `num-bins`."
-  [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZeroPlumatic]
+  [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZero]
   (u/round-to-decimals 5 (/ (- max-value min-value)
                             num-bins)))
 
-(s/defn ^:private calculate-num-bins :- su/IntGreaterThanZeroPlumatic
+(s/defn ^:private calculate-num-bins :- su/IntGreaterThanZero
   "Calculate number of bins of width `bin-width` required to cover interval [`min-value`, `max-value`]."
   [min-value :- s/Num
    max-value :- s/Num
@@ -72,9 +72,9 @@
        1))
 
 (s/defn ^:private resolve-default-strategy :- [(s/one (s/enum :bin-width :num-bins) "strategy")
-                                               (s/one {:bin-width s/Num, :num-bins su/IntGreaterThanZeroPlumatic} "opts")]
+                                               (s/one {:bin-width s/Num, :num-bins su/IntGreaterThanZero} "opts")]
   "Determine the approprate strategy & options to use when `:default` strategy was specified."
-  [metadata  :- {(s/optional-key :semantic_type) (s/maybe su/FieldSemanticOrRelationTypePlumatic), s/Any s/Any}
+  [metadata  :- {(s/optional-key :semantic_type) (s/maybe su/FieldSemanticOrRelationType), s/Any s/Any}
    min-value :- s/Num
    max-value :- s/Num]
   (if (isa? (:semantic_type metadata) :type/Coordinate)
@@ -103,7 +103,7 @@
 (def ^:private ^:const pleasing-numbers [1 1.25 2 2.5 3 5 7.5 10])
 
 (s/defn ^:private nicer-bin-width
-  [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZeroPlumatic]
+  [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZero]
   (let [min-bin-width (calculate-bin-width min-value max-value num-bins)
         scale         (expt 10 (u/order-of-magnitude min-bin-width))]
     (->> pleasing-numbers
@@ -126,11 +126,11 @@
          (drop-while (partial apply not=))
          ffirst)))
 
-(s/defn ^:private nicer-breakout* :- su/MapPlumatic
+(s/defn ^:private nicer-breakout* :- su/Map
   "Humanize binning: extend interval to start and end on a \"nice\" number and, when number of bins is fixed, have a
   \"nice\" step (bin width)."
   [strategy                                         :- mbql.s/BinningStrategyName
-   {:keys [min-value max-value bin-width num-bins]} :- su/MapPlumatic]
+   {:keys [min-value max-value bin-width num-bins]} :- su/Map]
   (let [bin-width             (if (= strategy :num-bins)
                                 (nicer-bin-width min-value max-value num-bins)
                                 bin-width)
@@ -142,8 +142,8 @@
                   (calculate-num-bins min-value max-value bin-width))
      :bin-width bin-width}))
 
-(s/defn ^:private nicer-breakout :- (s/maybe su/MapPlumatic)
-  [strategy :- mbql.s/BinningStrategyName, opts :- su/MapPlumatic]
+(s/defn ^:private nicer-breakout :- (s/maybe su/Map)
+  [strategy :- mbql.s/BinningStrategyName, opts :- su/Map]
   (let [f (partial nicer-breakout* strategy)]
     ((fixed-point f) opts)))
 
@@ -166,7 +166,7 @@
     (resolve-default-strategy metadata min-value max-value)))
 
 (s/defn ^:private matching-metadata
-  [field-id-or-name :- (s/cond-pre su/IntGreaterThanZeroPlumatic su/NonBlankStringPlumatic) source-metadata]
+  [field-id-or-name :- (s/cond-pre su/IntGreaterThanZero su/NonBlankString) source-metadata]
   (if (integer? field-id-or-name)
     ;; for Field IDs, just fetch the Field from the Store
     (qp.store/field field-id-or-name)
diff --git a/src/metabase/query_processor/middleware/expand_macros.clj b/src/metabase/query_processor/middleware/expand_macros.clj
index ede25fc3b9dcf5e5182e07d9ecf831888f8ff63e..5ff371fc0661d2fca993685d07fb323da2a79a38 100644
--- a/src/metabase/query_processor/middleware/expand_macros.clj
+++ b/src/metabase/query_processor/middleware/expand_macros.clj
@@ -51,15 +51,15 @@
   (mbql.u/match query [:metric (_ :guard (complement mbql.u/ga-id?))]))
 
 (def ^:private MetricInfo
-  {:id         su/IntGreaterThanZeroPlumatic
-   :name       su/NonBlankStringPlumatic
+  {:id         su/IntGreaterThanZero
+   :name       su/NonBlankString
    :definition {:aggregation             [(s/one mbql.s/Aggregation "aggregation clause")]
                 (s/optional-key :filter) (s/maybe mbql.s/Filter)
                 s/Keyword                s/Any}})
 
 (def ^:private ^{:arglists '([metric-info])} metric-info-validation-errors (s/checker MetricInfo))
 
-(s/defn ^:private metric-clauses->id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo}
+(s/defn ^:private metric-clauses->id->info :- {su/IntGreaterThanZero MetricInfo}
   [metric-clauses :- [mbql.s/metric]]
   (when (seq metric-clauses)
     (m/index-by :id (for [metric (db/select [Metric :id :name :definition] :id [:in (set (map second metric-clauses))])
@@ -70,7 +70,7 @@
                       metric))))
 
 (s/defn ^:private add-metrics-filters-this-level :- mbql.s/MBQLQuery
-  [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo}]
+  [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZero MetricInfo}]
   (let [filters (for [{{filter-clause :filter} :definition} (vals this-level-metric-id->info)
                       :when filter-clause]
                   filter-clause)]
@@ -95,7 +95,7 @@
       [:aggregation-options &match {:display-name metric-name}])))
 
 (s/defn ^:private replace-metrics-aggregations-this-level :- mbql.s/MBQLQuery
-  [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo}]
+  [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZero MetricInfo}]
   (letfn [(metric [metric-id]
             (or (get this-level-metric-id->info metric-id)
                 (throw (ex-info (tru "Metric {0} does not exist, or is invalid." metric-id)
@@ -119,7 +119,7 @@
       [:metric (metric-id :guard (complement mbql.u/ga-id?))]
       (metric-info->ag-clause (metric metric-id) {:use-metric-name-as-display-name? true}))))
 
-(s/defn ^:private metric-ids-this-level :- (s/maybe #{su/IntGreaterThanZeroPlumatic})
+(s/defn ^:private metric-ids-this-level :- (s/maybe #{su/IntGreaterThanZero})
   [inner-query]
   (when (map? inner-query)
     (when-let [aggregations (:aggregation inner-query)]
@@ -133,19 +133,19 @@
                                                         mbql.s/MBQLQuery
                                                         (complement metric-ids-this-level)
                                                         "Inner MBQL query with no :metric clauses at this level")
-  [inner-query :- mbql.s/MBQLQuery metric-id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo}]
+  [inner-query :- mbql.s/MBQLQuery metric-id->info :- {su/IntGreaterThanZero MetricInfo}]
   (let [this-level-metric-ids      (metric-ids-this-level inner-query)
         this-level-metric-id->info (select-keys metric-id->info this-level-metric-ids)]
     (-> inner-query
         (add-metrics-filters-this-level this-level-metric-id->info)
         (replace-metrics-aggregations-this-level this-level-metric-id->info))))
 
-(s/defn ^:private expand-metrics-clauses :- su/MapPlumatic
+(s/defn ^:private expand-metrics-clauses :- su/Map
   "Add appropriate `filter` and `aggregation` clauses for a sequence of Metrics.
 
     (expand-metrics-clauses {:query {}} [[:metric 10]])
     ;; -> {:query {:aggregation [[:count]], :filter [:= [:field-id 10] 20]}}"
-  [query :- su/MapPlumatic metric-id->info :- (su/non-empty {su/IntGreaterThanZeroPlumatic MetricInfo})]
+  [query :- su/Map metric-id->info :- (su/non-empty {su/IntGreaterThanZero MetricInfo})]
   (mbql.u/replace query
     (m :guard metric-ids-this-level)
     (-> m
diff --git a/src/metabase/query_processor/middleware/fetch_source_query.clj b/src/metabase/query_processor/middleware/fetch_source_query.clj
index 6816c9c70b58388a87d625c8067ffcb9c0242150..20607496d9f3180b86b9a31538a2b426d8904cb8 100644
--- a/src/metabase/query_processor/middleware/fetch_source_query.clj
+++ b/src/metabase/query_processor/middleware/fetch_source_query.clj
@@ -59,7 +59,7 @@
    {:database        mbql.s/DatabaseID
     :source-metadata [mbql.s/SourceQueryMetadata]
     :source-query    mbql.s/SourceQuery
-    :source-card-id  su/IntGreaterThanZeroPlumatic
+    :source-card-id  su/IntGreaterThanZero
     s/Keyword        s/Any}
    (complement :source-table)
    "`:source-table` should be removed"))
@@ -89,11 +89,11 @@
 ;;; |                                       Resolving card__id -> source query                                       |
 ;;; +----------------------------------------------------------------------------------------------------------------+
 
-(s/defn ^:private trim-sql-query :- su/NonBlankStringPlumatic
+(s/defn ^:private trim-sql-query :- su/NonBlankString
   "Native queries can have trailing SQL comments. This works when executed directly, but when we use the query in a
   nested query, we wrap it in another query, which can cause the last part of the query to be unintentionally
   commented out, causing it to fail. This function removes any trailing SQL comment."
-  [card-id :- su/IntGreaterThanZeroPlumatic, query-str :- su/NonBlankStringPlumatic]
+  [card-id :- su/IntGreaterThanZero, query-str :- su/NonBlankString]
   (let [trimmed-string (str/replace query-str #"--.*(\n|$)" "")]
     (if (= query-str trimmed-string)
       query-str
@@ -112,9 +112,9 @@
 (s/defn card-id->source-query-and-metadata :- SourceQueryAndMetadata
   "Return the source query info for Card with `card-id`. Pass true as the optional second arg `log?` to enable
   logging. (The circularity check calls this and will print more than desired)"
-  ([card-id :- su/IntGreaterThanZeroPlumatic]
+  ([card-id :- su/IntGreaterThanZero]
    (card-id->source-query-and-metadata card-id false))
-  ([card-id :- su/IntGreaterThanZeroPlumatic log? :- s/Bool]
+  ([card-id :- su/IntGreaterThanZero log? :- s/Bool]
    (let [;; todo: we need to cache this. We are running this in preprocess, compile, and then again
          card           (or (db/select-one Card :id card-id)
                             (throw (ex-info (tru "Card {0} does not exist." card-id)
@@ -167,7 +167,7 @@
                                  persisted? sub-cached-field-refs)}
        dataset? (assoc :source-query/dataset? dataset?)))))
 
-(s/defn ^:private source-table-str->card-id :- su/IntGreaterThanZeroPlumatic
+(s/defn ^:private source-table-str->card-id :- su/IntGreaterThanZero
   [source-table-str :- mbql.s/source-table-card-id-regex]
   (when-let [[_ card-id-str] (re-find #"^card__(\d+)$" source-table-str)]
     (Integer/parseInt card-id-str)))
@@ -265,22 +265,22 @@
     (&match :guard (every-pred map? :database (comp integer? :database)))
     (recur (dissoc &match :database))))
 
-(s/defn ^:private extract-resolved-card-id :- {:card-id (s/maybe su/IntGreaterThanZeroPlumatic)
-                                               :query   su/MapPlumatic}
+(s/defn ^:private extract-resolved-card-id :- {:card-id (s/maybe su/IntGreaterThanZero)
+                                               :query   su/Map}
   "If the ID of the Card we've resolved (`:source-card-id`) was added by a previous step, add it
   to `:query` `:info` (so it can be included in the QueryExecution log), then return a map with the resolved
   `:card-id` and updated `:query`."
-  [query :- su/MapPlumatic]
+  [query :- su/Map]
   (let [card-id (get-in query [:query :source-card-id])]
     {:query   (cond-> query
                 card-id (update-in [:info :card-id] #(or % card-id)))
      :card-id card-id}))
 
-(s/defn ^:private resolve-all :- {:card-id (s/maybe su/IntGreaterThanZeroPlumatic)
-                                  :query   su/MapPlumatic}
+(s/defn ^:private resolve-all :- {:card-id (s/maybe su/IntGreaterThanZero)
+                                  :query   su/Map}
   "Recursively replace all Card ID source tables in `query` with resolved `:source-query` and `:source-metadata`. Since
   the `:database` is only useful for top-level source queries, we'll remove it from all other levels."
-  [query :- su/MapPlumatic]
+  [query :- su/Map]
   ;; if a `:source-card-id` is already in the query, remove it, so we don't pull user-supplied input up into `:info`
   ;; allowing someone to bypass permissions
   (-> (m/dissoc-in query [:query :source-card-id])
@@ -290,7 +290,7 @@
       remove-unneeded-database-ids
       extract-resolved-card-id))
 
-(s/defn ^:private resolve-card-id-source-tables* :- {:card-id (s/maybe su/IntGreaterThanZeroPlumatic)
+(s/defn ^:private resolve-card-id-source-tables* :- {:card-id (s/maybe su/IntGreaterThanZero)
                                                      :query   FullyResolvedQuery}
   "Resolve `card__n`-style `:source-tables` in `query`."
   [{inner-query :query, :as outer-query} :- mbql.s/Query]
diff --git a/src/metabase/query_processor/middleware/permissions.clj b/src/metabase/query_processor/middleware/permissions.clj
index 5d7775b139e9637315f97548261673e9ecb7e605..7aae7bd5b082833670edbf6b449a909bad2d0d18 100644
--- a/src/metabase/query_processor/middleware/permissions.clj
+++ b/src/metabase/query_processor/middleware/permissions.clj
@@ -57,7 +57,7 @@
 
 (s/defn ^:private check-card-read-perms
   "Check that the current user has permissions to read Card with `card-id`, or throw an Exception. "
-  [card-id :- su/IntGreaterThanZeroPlumatic]
+  [card-id :- su/IntGreaterThanZero]
   (let [card (or (db/select-one [Card :collection_id] :id card-id)
                  (throw (ex-info (tru "Card {0} does not exist." card-id)
                                  {:type    qp.error-type/invalid-query
@@ -91,7 +91,7 @@
 
 (s/defn ^:private check-query-permissions*
   "Check that User with `user-id` has permissions to run `query`, or throw an exception."
-  [outer-query :- su/MapPlumatic]
+  [outer-query :- su/Map]
   (when *current-user-id*
     (log/tracef "Checking query permissions. Current user perms set = %s" (pr-str @*current-user-permissions-set*))
     (if *card-id*
@@ -128,7 +128,7 @@
 
 (s/defn check-query-action-permissions*
   "Check that User with `user-id` has permissions to run query action `query`, or throw an exception."
-  [outer-query :- su/MapPlumatic]
+  [outer-query :- su/Map]
   (log/tracef "Checking query permissions. Current user perms set = %s" (pr-str @*current-user-permissions-set*))
   (when *card-id*
     (check-card-read-perms *card-id*))
diff --git a/src/metabase/query_processor/middleware/resolve_joined_fields.clj b/src/metabase/query_processor/middleware/resolve_joined_fields.clj
index e6ee0121206c7ee68846d100635e95b33467b0fd..8ac2f1f0f135ebb4c3c4031817bffd958b695725 100644
--- a/src/metabase/query_processor/middleware/resolve_joined_fields.clj
+++ b/src/metabase/query_processor/middleware/resolve_joined_fields.clj
@@ -13,7 +13,7 @@
    [schema.core :as s]))
 
 (def ^:private InnerQuery
-  (s/constrained su/MapPlumatic (every-pred (some-fn :source-table :source-query :joins)
+  (s/constrained su/Map (every-pred (some-fn :source-table :source-query :joins)
                                     (complement :condition))))
 
 (s/defn ^:private add-join-alias
diff --git a/src/metabase/query_processor/middleware/resolve_source_table.clj b/src/metabase/query_processor/middleware/resolve_source_table.clj
index 38dbda66660090e44e28414c5ec6e0c42271ce9a..22569f74d82a8161187c6f19ad6866773d2042e6 100644
--- a/src/metabase/query_processor/middleware/resolve_source_table.clj
+++ b/src/metabase/query_processor/middleware/resolve_source_table.clj
@@ -18,7 +18,7 @@
         (tru "Invalid :source-table ''{0}'': should be resolved to a Table ID by now." (:source-table m))
         {:form m}))))
 
-(s/defn ^:private query->source-table-ids :- (s/maybe (su/non-empty #{su/IntGreaterThanZeroPlumatic}))
+(s/defn ^:private query->source-table-ids :- (s/maybe (su/non-empty #{su/IntGreaterThanZero}))
   "Fetch a set of all `:source-table` IDs anywhere in `query`."
   [query]
   (some->
diff --git a/src/metabase/query_processor/store.clj b/src/metabase/query_processor/store.clj
index da777ab6af91fe209be386bcb64350e015473e8a..5148d29bf047232af73d9dd296e523a256ada26c 100644
--- a/src/metabase/query_processor/store.clj
+++ b/src/metabase/query_processor/store.clj
@@ -64,11 +64,11 @@
 (def ^:private DatabaseInstanceWithRequiredStoreKeys
   (s/both
    (mi/InstanceOf Database)
-   {:id       su/IntGreaterThanZeroPlumatic
+   {:id       su/IntGreaterThanZero
     :engine   s/Keyword
-    :name     su/NonBlankStringPlumatic
-    :details  su/MapPlumatic
-    :settings (s/maybe su/MapPlumatic)
+    :name     su/NonBlankString
+    :details  su/Map
+    :settings (s/maybe su/Map)
     s/Any     s/Any}))
 
 (def ^:private table-columns-to-fetch
@@ -82,7 +82,7 @@
   (s/both
    (mi/InstanceOf Table)
    {:schema (s/maybe s/Str)
-    :name   su/NonBlankStringPlumatic
+    :name   su/NonBlankString
     s/Any   s/Any}))
 
 
@@ -109,19 +109,19 @@
 (def ^:private FieldInstanceWithRequiredStorekeys
   (s/both
    (mi/InstanceOf Field)
-   {:name                               su/NonBlankStringPlumatic
-    :display_name                       su/NonBlankStringPlumatic
+   {:name                               su/NonBlankString
+    :display_name                       su/NonBlankString
     :description                        (s/maybe s/Str)
-    :database_type                      su/NonBlankStringPlumatic
-    :base_type                          su/FieldTypePlumatic
+    :database_type                      su/NonBlankString
+    :base_type                          su/FieldType
     ;; there's a tension as we sometimes store fields from the db, and sometimes store computed fields. ideally we
     ;; would make everything just use base_type.
-    (s/optional-key :effective_type)    (s/maybe su/FieldTypePlumatic)
-    (s/optional-key :coercion_strategy) (s/maybe su/CoercionStrategyPlumatic)
-    :semantic_type                      (s/maybe su/FieldSemanticOrRelationTypePlumatic)
-    :fingerprint                        (s/maybe su/MapPlumatic)
-    :parent_id                          (s/maybe su/IntGreaterThanZeroPlumatic)
-    :nfc_path                           (s/maybe [su/NonBlankStringPlumatic])
+    (s/optional-key :effective_type)    (s/maybe su/FieldType)
+    (s/optional-key :coercion_strategy) (s/maybe su/CoercionStrategy)
+    :semantic_type                      (s/maybe su/FieldSemanticOrRelationType)
+    :fingerprint                        (s/maybe su/Map)
+    :parent_id                          (s/maybe su/IntGreaterThanZero)
+    :nfc_path                           (s/maybe [su/NonBlankString])
     s/Any                               s/Any}))
 
 
@@ -150,7 +150,7 @@
 
 ;;; ----------------------- Fetching objects from application DB, and saving them in the store -----------------------
 
-(s/defn ^:private db-id :- su/IntGreaterThanZeroPlumatic
+(s/defn ^:private db-id :- su/IntGreaterThanZero
   []
   (or (get-in @*store* [:database :id])
       (throw (Exception. (tru "Cannot store Tables or Fields before Database is stored.")))))
@@ -159,7 +159,7 @@
   "Fetch the Database this query will run against from the application database, and store it in the QP Store for the
   duration of the current query execution. If Database has already been fetched, this function will no-op. Throws an
   Exception if Table does not exist."
-  [database-id :- su/IntGreaterThanZeroPlumatic]
+  [database-id :- su/IntGreaterThanZero]
   (if-let [existing-db-id (get-in @*store* [:database :id])]
     ;; if there's already a DB in the Store, double-check it has the same ID as the one that we were asked to fetch
     (when-not (= existing-db-id database-id)
@@ -174,8 +174,8 @@
 (def ^:private IDs
   (s/maybe
    (s/cond-pre
-    #{su/IntGreaterThanZeroPlumatic}
-    [su/IntGreaterThanZeroPlumatic])))
+    #{su/IntGreaterThanZero}
+    [su/IntGreaterThanZero])))
 
 (s/defn fetch-and-store-tables!
   "Fetch Table(s) from the application database, and store them in the QP Store for the duration of the current query
@@ -248,7 +248,7 @@
 
 (s/defn table :- TableInstanceWithRequiredStoreKeys
   "Fetch Table with `table-id` from the QP Store. Throws an Exception if valid item is not returned."
-  [table-id :- su/IntGreaterThanZeroPlumatic]
+  [table-id :- su/IntGreaterThanZero]
   (*table* table-id))
 
 (defn- default-field
@@ -263,7 +263,7 @@
 
 (s/defn field :- FieldInstanceWithRequiredStorekeys
   "Fetch Field with `field-id` from the QP Store. Throws an Exception if valid item is not returned."
-  [field-id :- su/IntGreaterThanZeroPlumatic]
+  [field-id :- su/IntGreaterThanZero]
   (*field* field-id))
 
 
diff --git a/src/metabase/query_processor/util.clj b/src/metabase/query_processor/util.clj
index db53076c1955fea10d3f28833dc252f68f585665..269a781d897902278c01e46bbcc13c14f56225a2 100644
--- a/src/metabase/query_processor/util.clj
+++ b/src/metabase/query_processor/util.clj
@@ -59,7 +59,7 @@
 (s/defn ^:deprecated normalize-token :- s/Keyword
   "Convert a string or keyword in various cases (`lisp-case`, `snake_case`, or `SCREAMING_SNAKE_CASE`) to a lisp-cased
   keyword."
-  [token :- su/KeywordOrStringPlumatic]
+  [token :- su/KeywordOrString]
   (-> (name token)
       str/lower-case
       (str/replace #"_" "-")
diff --git a/src/metabase/server/middleware/browser_cookie.clj b/src/metabase/server/middleware/browser_cookie.clj
index dfeda32036c6a811cad348ddf54418bc5a89d98e..0f4ac584ebe974cc34a9b8d75e36313ec9e1bcb4 100644
--- a/src/metabase/server/middleware/browser_cookie.clj
+++ b/src/metabase/server/middleware/browser_cookie.clj
@@ -29,7 +29,7 @@
            {:same-site :none, :secure true}
            {:same-site :lax})))
 
-(s/defn ^:private add-browser-id-cookie [request response browser-id :- su/NonBlankStringPlumatic]
+(s/defn ^:private add-browser-id-cookie [request response browser-id :- su/NonBlankString]
   (response/set-cookie response browser-id-cookie-name browser-id (cookie-options request)))
 
 (defn ensure-browser-id-cookie
diff --git a/src/metabase/server/request/util.clj b/src/metabase/server/request/util.clj
index bf93a0818e291a25d4b0ffb3bfad84b19153f5ac..e81a5ad6fdfa398efde20599aff0c1f6121a596c 100644
--- a/src/metabase/server/request/util.clj
+++ b/src/metabase/server/request/util.clj
@@ -89,9 +89,9 @@
 
 (def DeviceInfo
   "Schema for the device info returned by `device-info`."
-  {:device_id          su/NonBlankStringPlumatic
-   :device_description su/NonBlankStringPlumatic
-   :ip_address         su/NonBlankStringPlumatic})
+  {:device_id          su/NonBlankString
+   :device_description su/NonBlankString
+   :ip_address         su/NonBlankString})
 
 (s/defn device-info :- DeviceInfo
   "Information about the device that made this request, as recorded by the `LoginHistory` table."
@@ -137,10 +137,10 @@
   5000)
 
 (def ^:private IPAddress
-  (s/constrained su/NonBlankStringPlumatic u/ip-address? "valid IP address string"))
+  (s/constrained su/NonBlankString u/ip-address? "valid IP address string"))
 
 ;; TODO -- replace with something better, like built-in database once we find one that's GPL compatible
-(s/defn geocode-ip-addresses :- (s/maybe {IPAddress {:description su/NonBlankStringPlumatic
+(s/defn geocode-ip-addresses :- (s/maybe {IPAddress {:description su/NonBlankString
                                                      :timezone    (s/maybe java.time.ZoneId)}})
   "Geocode multiple IP addresses, returning a map of IP address -> info, with each info map containing human-friendly
   `:description` of the location and a `java.time.ZoneId` `:timezone`, if that information is available."
diff --git a/src/metabase/sync/analyze/classifiers/category.clj b/src/metabase/sync/analyze/classifiers/category.clj
index f872258c71067f2f6df422b24ea45fdec647ae04..3466091056ea6bc3d7ad372611cd5033226d1dc4 100644
--- a/src/metabase/sync/analyze/classifiers/category.clj
+++ b/src/metabase/sync/analyze/classifiers/category.clj
@@ -30,7 +30,7 @@
       (isa? semantic_type :type/FK)))
 
 (s/defn ^:private field-should-be-category? :- (s/maybe s/Bool)
-  [fingerprint :- (s/maybe i/Fingerprint), field :- su/MapPlumatic]
+  [fingerprint :- (s/maybe i/Fingerprint), field :- su/Map]
   (let [distinct-count (get-in fingerprint [:global :distinct-count])
         nil%           (get-in fingerprint [:global :nil%])]
     ;; Only mark a Field as a Category if it doesn't already have a semantic type.
diff --git a/src/metabase/sync/analyze/classifiers/name.clj b/src/metabase/sync/analyze/classifiers/name.clj
index b0220dc58e8d81df8ee1af2505abe0ffe20a509c..abcd24a52053cef5ef84044612aaa7d62742d45b 100644
--- a/src/metabase/sync/analyze/classifiers/name.clj
+++ b/src/metabase/sync/analyze/classifiers/name.clj
@@ -119,9 +119,9 @@
     (assert (or (isa? semantic-type :Semantic/*)
                 (isa? semantic-type :Relation/*)))))
 
-(s/defn ^:private semantic-type-for-name-and-base-type :- (s/maybe su/FieldSemanticOrRelationTypePlumatic)
+(s/defn ^:private semantic-type-for-name-and-base-type :- (s/maybe su/FieldSemanticOrRelationType)
   "If `name` and `base-type` matches a known pattern, return the `semantic_type` we should assign to it."
-  [field-name :- su/NonBlankStringPlumatic, base-type :- su/FieldTypePlumatic]
+  [field-name :- su/NonBlankString, base-type :- su/FieldType]
   (let [field-name (str/lower-case field-name)]
     (some (fn [[name-pattern valid-base-types semantic-type]]
             (when (and (some (partial isa? base-type) valid-base-types)
diff --git a/src/metabase/sync/analyze/classifiers/text_fingerprint.clj b/src/metabase/sync/analyze/classifiers/text_fingerprint.clj
index 1a642817c7a6c4b6c39a8593bcff0a305fbbe3c6..c2097d259aeed64e01b550163f3ea56bf6ce7a1a 100644
--- a/src/metabase/sync/analyze/classifiers/text_fingerprint.clj
+++ b/src/metabase/sync/analyze/classifiers/text_fingerprint.clj
@@ -33,7 +33,7 @@
    :percent-email [:type/Email          percent-valid-threshold]
    :percent-state [:type/State          lower-percent-valid-threshold]})
 
-(s/defn ^:private infer-semantic-type-for-text-fingerprint :- (s/maybe su/FieldTypePlumatic)
+(s/defn ^:private infer-semantic-type-for-text-fingerprint :- (s/maybe su/FieldType)
   "Check various percentages inside the TEXT-FINGERPRINT and return the corresponding semantic type to mark the Field
   as if the percent passes the threshold."
   [text-fingerprint :- i/TextFingerprint]
diff --git a/src/metabase/sync/analyze/fingerprint.clj b/src/metabase/sync/analyze/fingerprint.clj
index 9546cb338303351f447cb10922640912d23c9d64..aa54d1b2410cf5ab61fc84575d08b28a5a9fbd40 100644
--- a/src/metabase/sync/analyze/fingerprint.clj
+++ b/src/metabase/sync/analyze/fingerprint.clj
@@ -96,10 +96,10 @@
 ;;        (fingerprint_version < 2 AND
 ;;         base_type IN ("type/Text", "type/SerializedJSON")))
 
-(s/defn ^:private base-types->descendants :- #{su/FieldTypeKeywordOrStringPlumatic}
+(s/defn ^:private base-types->descendants :- #{su/FieldTypeKeywordOrString}
   "Given a set of BASE-TYPES return an expanded set that includes those base types as well as all of their
    descendants. These types are converted to strings so HoneySQL doesn't confuse them for columns."
-  [base-types :- #{su/FieldTypePlumatic}]
+  [base-types :- #{su/FieldType}]
   (->> (for [base-type base-types]
          (cons base-type (descendants base-type)))
        (reduce set/union)
diff --git a/src/metabase/sync/analyze/query_results.clj b/src/metabase/sync/analyze/query_results.clj
index 8015a2365e725df0462097afb08ad33b459b0190..f8008003e15358bcc096395b19a8fa1b85413549 100644
--- a/src/metabase/sync/analyze/query_results.clj
+++ b/src/metabase/sync/analyze/query_results.clj
@@ -20,7 +20,7 @@
 
 (def ^:private DateTimeUnitKeywordOrString
   "Schema for a valid datetime unit string like \"default\" or \"minute-of-hour\"."
-  (s/constrained su/KeywordOrStringPlumatic
+  (s/constrained su/KeywordOrString
                  #(mbql.preds/DateTimeUnit? (keyword %))
                  "Valid field datetime unit keyword or string"))
 
@@ -31,11 +31,11 @@
   {:name                                s/Str
    :display_name                        s/Str
    (s/optional-key :description)        (s/maybe s/Str)
-   :base_type                           su/FieldTypeKeywordOrStringPlumatic
-   (s/optional-key :semantic_type)      (s/maybe su/FieldSemanticOrRelationTypeKeywordOrStringPlumatic)
+   :base_type                           su/FieldTypeKeywordOrString
+   (s/optional-key :semantic_type)      (s/maybe su/FieldSemanticOrRelationTypeKeywordOrString)
    (s/optional-key :unit)               (s/maybe DateTimeUnitKeywordOrString)
    (s/optional-key :fingerprint)        (s/maybe i/Fingerprint)
-   (s/optional-key :id)                 (s/maybe su/IntGreaterThanZeroPlumatic)
+   (s/optional-key :id)                 (s/maybe su/IntGreaterThanZero)
    ;; only optional because it's not present right away, but it should be present at the end.
    (s/optional-key :field_ref)          (s/cond-pre
                                           mbql.s/FieldOrAggregationReference
diff --git a/src/metabase/sync/interface.clj b/src/metabase/sync/interface.clj
index b4af454474f06e029dea20760e44fbae081c98ff..7146c6e7743b45349f27f43c22d3f3bff4a72ee8 100644
--- a/src/metabase/sync/interface.clj
+++ b/src/metabase/sync/interface.clj
@@ -10,26 +10,26 @@
 
 (def DatabaseMetadataTable
   "Schema for the expected output of `describe-database` for a Table."
-  {:name                         su/NonBlankStringPlumatic
-   :schema                       (s/maybe su/NonBlankStringPlumatic)
+  {:name                         su/NonBlankString
+   :schema                       (s/maybe su/NonBlankString)
    ;; `:description` in this case should be a column/remark on the Table, if there is one.
    (s/optional-key :description) (s/maybe s/Str)})
 
 (def DatabaseMetadata
   "Schema for the expected output of `describe-database`."
   {:tables                   #{DatabaseMetadataTable}
-   (s/optional-key :version) (s/maybe su/NonBlankStringPlumatic)})
+   (s/optional-key :version) (s/maybe su/NonBlankString)})
 
 (def TableMetadataField
   "Schema for a given Field as provided in `describe-table`."
-  {:name                               su/NonBlankStringPlumatic
-   :database-type                      (s/maybe su/NonBlankStringPlumatic) ; blank if the Field is all NULL & untyped, i.e. in Mongo
-   :base-type                          su/FieldTypePlumatic
-   :database-position                  su/IntGreaterThanOrEqualToZeroPlumatic
-   (s/optional-key :semantic-type)     (s/maybe su/FieldSemanticOrRelationTypePlumatic)
-   (s/optional-key :effective-type)    (s/maybe su/FieldTypePlumatic)
-   (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategyPlumatic)
-   (s/optional-key :field-comment)     (s/maybe su/NonBlankStringPlumatic)
+  {:name                               su/NonBlankString
+   :database-type                      (s/maybe su/NonBlankString) ; blank if the Field is all NULL & untyped, i.e. in Mongo
+   :base-type                          su/FieldType
+   :database-position                  su/IntGreaterThanOrEqualToZero
+   (s/optional-key :semantic-type)     (s/maybe su/FieldSemanticOrRelationType)
+   (s/optional-key :effective-type)    (s/maybe su/FieldType)
+   (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategy)
+   (s/optional-key :field-comment)     (s/maybe su/NonBlankString)
    (s/optional-key :pk?)               s/Bool
    (s/optional-key :nested-fields)     #{(s/recursive #'TableMetadataField)}
    (s/optional-key :nfc-path)          [s/Any]
@@ -40,8 +40,8 @@
 
 (def TableMetadata
   "Schema for the expected output of `describe-table`."
-  {:name                         su/NonBlankStringPlumatic
-   :schema                       (s/maybe su/NonBlankStringPlumatic)
+  {:name                         su/NonBlankString
+   :schema                       (s/maybe su/NonBlankString)
    :fields                       #{TableMetadataField}
    (s/optional-key :description) (s/maybe s/Str)})
 
@@ -51,10 +51,10 @@
 
 (def FKMetadataEntry
   "Schema for an individual entry in `FKMetadata`."
-  {:fk-column-name   su/NonBlankStringPlumatic
-   :dest-table       {:name   su/NonBlankStringPlumatic
-                      :schema (s/maybe su/NonBlankStringPlumatic)}
-   :dest-column-name su/NonBlankStringPlumatic})
+  {:fk-column-name   su/NonBlankString
+   :dest-table       {:name   su/NonBlankString
+                      :schema (s/maybe su/NonBlankString)}
+   :dest-column-name su/NonBlankString})
 
 (def FKMetadata
   "Schema for the expected output of `describe-table-fks`."
@@ -68,7 +68,7 @@
 (def DatabaseInstance             "Schema for a valid instance of a Metabase Database." (mi/InstanceOf Database))
 (def TableInstance                "Schema for a valid instance of a Metabase Table."    (mi/InstanceOf Table))
 (def FieldInstance                "Schema for a valid instance of a Metabase Field."    (mi/InstanceOf Field))
-(def ResultColumnMetadataInstance "Schema for result column metadata."                  su/MapPlumatic)
+(def ResultColumnMetadataInstance "Schema for result column metadata."                  su/Map)
 
 
 ;;; +----------------------------------------------------------------------------------------------------------------+
diff --git a/src/metabase/sync/sync_metadata/dbms_version.clj b/src/metabase/sync/sync_metadata/dbms_version.clj
index a484cd765f70bd5fa3da1c0411f632fed791dc93..838576d89f6b8faf93377fe23ae5a38546c49429 100644
--- a/src/metabase/sync/sync_metadata/dbms_version.clj
+++ b/src/metabase/sync/sync_metadata/dbms_version.clj
@@ -10,7 +10,7 @@
 
 (def DBMSVersion
   "Schema for the expected output of `describe-table-fks`."
-  {:version  su/NonBlankStringPlumatic
+  {:version  su/NonBlankString
    s/Keyword s/Any})
 
 (s/defn sync-dbms-version!
diff --git a/src/metabase/sync/sync_metadata/fields.clj b/src/metabase/sync/sync_metadata/fields.clj
index b8e3bca2a03ffd907a27a4b73fc7ddecbd6dde4f..dd76b164c0ad7a223b7f07ae8acde3d429a764ef 100644
--- a/src/metabase/sync/sync_metadata/fields.clj
+++ b/src/metabase/sync/sync_metadata/fields.clj
@@ -53,7 +53,7 @@
 ;;; |                                            PUTTING IT ALL TOGETHER                                             |
 ;;; +----------------------------------------------------------------------------------------------------------------+
 
-(s/defn ^:private sync-and-update! :- su/IntGreaterThanOrEqualToZeroPlumatic
+(s/defn ^:private sync-and-update! :- su/IntGreaterThanOrEqualToZero
   "Sync Field instances (i.e., rows in the Field table in the Metabase application DB) for a Table, and update metadata
   properties (e.g. base type and comment/remark) as needed. Returns number of Fields synced."
   [table :- i/TableInstance, db-metadata :- #{i/TableMetadataField}]
@@ -75,8 +75,8 @@
         :updated-fields (sync-and-update! table db-metadata)}))))
 
 
-(s/defn sync-fields! :- (s/maybe {:updated-fields su/IntGreaterThanOrEqualToZeroPlumatic
-                                  :total-fields   su/IntGreaterThanOrEqualToZeroPlumatic})
+(s/defn sync-fields! :- (s/maybe {:updated-fields su/IntGreaterThanOrEqualToZero
+                                  :total-fields   su/IntGreaterThanOrEqualToZero})
   "Sync the Fields in the Metabase application database for all the Tables in a `database`."
   [database :- i/DatabaseInstance]
   (->> database
diff --git a/src/metabase/sync/sync_metadata/fields/common.clj b/src/metabase/sync/sync_metadata/fields/common.clj
index 6895bd299749cf90a3ce20c9ec3579085b8ee1ae..49b7cbbda22d13eea2aa0cb1001b6bb4bd1e9ea6 100644
--- a/src/metabase/sync/sync_metadata/fields/common.clj
+++ b/src/metabase/sync/sync_metadata/fields/common.clj
@@ -10,20 +10,20 @@
 
 (def ParentID
   "Schema for the `parent-id` of a Field, i.e. an optional ID."
-  (s/maybe su/IntGreaterThanZeroPlumatic))
+  (s/maybe su/IntGreaterThanZero))
 
 (def TableMetadataFieldWithID
   "Schema for `TableMetadataField` with an included ID of the corresponding Metabase Field object.
   `our-metadata` is always returned in this format. (The ID is needed in certain places so we know which Fields to
   retire, and the parent ID of any nested-fields.)"
   (assoc i/TableMetadataField
-    :id                             su/IntGreaterThanZeroPlumatic
+    :id                             su/IntGreaterThanZero
     (s/optional-key :nested-fields) #{(s/recursive #'TableMetadataFieldWithID)}))
 
 (def TableMetadataFieldWithOptionalID
   "Schema for either `i/TableMetadataField` (`db-metadata`) or `TableMetadataFieldWithID` (`our-metadata`)."
   (assoc i/TableMetadataField
-    (s/optional-key :id)            su/IntGreaterThanZeroPlumatic
+    (s/optional-key :id)            su/IntGreaterThanZero
     (s/optional-key :nested-fields) #{(s/recursive #'TableMetadataFieldWithOptionalID)}))
 
 (s/defn field-metadata-name-for-logging :- s/Str
@@ -39,7 +39,7 @@
   [field]
   (str/lower-case (:name field)))
 
-(s/defn semantic-type :- (s/maybe su/FieldSemanticOrRelationTypePlumatic)
+(s/defn semantic-type :- (s/maybe su/FieldSemanticOrRelationType)
   "Determine a the appropriate `semantic-type` for a Field with `field-metadata`."
   [field-metadata :- (s/maybe i/TableMetadataField)]
   (and field-metadata
diff --git a/src/metabase/sync/sync_metadata/fields/sync_instances.clj b/src/metabase/sync/sync_metadata/fields/sync_instances.clj
index bf7343895cdcf6df4abdbf4649f7dc203bd464d3..3404aabd9830abbc7f7598142be5bb62885db83d 100644
--- a/src/metabase/sync/sync_metadata/fields/sync_instances.clj
+++ b/src/metabase/sync/sync_metadata/fields/sync_instances.clj
@@ -98,7 +98,7 @@
   "Schema for the value returned by `sync-active-instances!`. Because we need to know about newly-inserted/reactivated
   parent Fields when recursively syncing nested Fields, we need to propogate the updates to `our-metadata` made by
   this function and pass them to other steps of the `sync-instances!` process."
-  {:num-updates  su/IntGreaterThanOrEqualToZeroPlumatic
+  {:num-updates  su/IntGreaterThanOrEqualToZero
    :our-metadata #{common/TableMetadataFieldWithID}})
 
 (s/defn ^:private sync-active-instances! :- Updates
@@ -141,7 +141,7 @@
   (when (db/update! Field (u/the-id metabase-field) :active false)
     1))
 
-(s/defn ^:private retire-fields! :- su/IntGreaterThanOrEqualToZeroPlumatic
+(s/defn ^:private retire-fields! :- su/IntGreaterThanOrEqualToZero
   "Mark inactive any Fields in the application database that are no longer present in the DB being synced. These
   Fields are ones that are in `our-metadata`, but not in `db-metadata`. Does *NOT* recurse over nested Fields.
   Returns `1` if a Field was marked inactive."
@@ -162,7 +162,7 @@
 
 (declare sync-instances!)
 
-(s/defn ^:private sync-nested-fields-of-one-field! :- (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)
+(s/defn ^:private sync-nested-fields-of-one-field! :- (s/maybe su/IntGreaterThanOrEqualToZero)
   "Recursively sync Field instances (i.e., rows in application DB) for nested Fields of a single Field, one or both
   `field-metadata` (from synced DB) and `metabase-field` (from application DB)."
   [table          :- i/TableInstance
@@ -178,7 +178,7 @@
        (set metabase-nested-fields)
        (some-> metabase-field u/the-id)))))
 
-(s/defn ^:private sync-nested-field-instances! :- (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)
+(s/defn ^:private sync-nested-field-instances! :- (s/maybe su/IntGreaterThanOrEqualToZero)
   "Recursively sync Field instances (i.e., rows in application DB) for *all* the nested Fields of all Fields in
   `db-metadata` and `our-metadata`.
   Not for the flattened nested fields for JSON columns in normal RDBMSes (nested field columns)"
@@ -194,7 +194,7 @@
                               metabase-field (get name->metabase-field field-name)]]
       (sync-nested-fields-of-one-field! table field-metadata metabase-field))))
 
-(s/defn sync-instances! :- su/IntGreaterThanOrEqualToZeroPlumatic
+(s/defn sync-instances! :- su/IntGreaterThanOrEqualToZero
   "Sync rows in the Field table with `db-metadata` describing the current schema of the Table currently being synced,
   creating Field objects or marking them active/inactive as needed."
   ([table        :- i/TableInstance
diff --git a/src/metabase/sync/sync_metadata/fields/sync_metadata.clj b/src/metabase/sync/sync_metadata/fields/sync_metadata.clj
index ffdb3797b0f78c45be19e68fb8985d93d0f7ffe4..6e793e7664528efd056add8baa1ee7c287e43cc6 100644
--- a/src/metabase/sync/sync_metadata/fields/sync_metadata.clj
+++ b/src/metabase/sync/sync_metadata/fields/sync_metadata.clj
@@ -111,7 +111,7 @@
 
 (declare update-metadata!)
 
-(s/defn ^:private update-nested-fields-metadata! :- su/IntGreaterThanOrEqualToZeroPlumatic
+(s/defn ^:private update-nested-fields-metadata! :- su/IntGreaterThanOrEqualToZero
   "Recursively call `update-metadata!` for all the nested Fields in a `metabase-field`."
   [table :- i/TableInstance, field-metadata :- i/TableMetadataField, metabase-field :- common/TableMetadataFieldWithID]
   (let [nested-fields-metadata (:nested-fields field-metadata)
@@ -120,7 +120,7 @@
       (update-metadata! table (set nested-fields-metadata) (set metabase-nested-fields))
       0)))
 
-(s/defn update-metadata! :- su/IntGreaterThanOrEqualToZeroPlumatic
+(s/defn update-metadata! :- su/IntGreaterThanOrEqualToZero
   "Make sure things like PK status and base-type are in sync with what has come back from the DB. Recursively updates
   nested Fields. Returns total number of Fields updated."
   [table        :- i/TableInstance
diff --git a/src/metabase/sync/sync_metadata/metabase_metadata.clj b/src/metabase/sync/sync_metadata/metabase_metadata.clj
index de717bfdf6905fa23b0f4267d21b626717e63f5f..5ee72f221838c7a82da3d82b4d9848f622bf217f 100644
--- a/src/metabase/sync/sync_metadata/metabase_metadata.clj
+++ b/src/metabase/sync/sync_metadata/metabase_metadata.clj
@@ -22,14 +22,14 @@
    [toucan.db :as db]))
 
 (def ^:private KeypathComponents
-  {:table-name (s/maybe su/NonBlankStringPlumatic)
-   :field-name (s/maybe su/NonBlankStringPlumatic)
+  {:table-name (s/maybe su/NonBlankString)
+   :field-name (s/maybe su/NonBlankString)
    :k          s/Keyword})
 
 (s/defn ^:private parse-keypath :- KeypathComponents
   "Parse a KEYPATH into components for easy use."
   ;; TODO: this does not support schemas in dbs :(
-  [keypath :- su/NonBlankStringPlumatic]
+  [keypath :- su/NonBlankString]
   ;; keypath will have one of three formats:
   ;; property (for database-level properties)
   ;; table_name.property
diff --git a/src/metabase/sync/util.clj b/src/metabase/sync/util.clj
index 53c5d4794f681398cc3791483a2cec34e11b03cc..e8fed7b1fcc5c6e5ed11af325bf79bbf606b1300 100644
--- a/src/metabase/sync/util.clj
+++ b/src/metabase/sync/util.clj
@@ -435,7 +435,7 @@
    StepRunMetadata))
 
 (s/defn ^:private create-task-history
-  [task-name :- su/NonBlankStringPlumatic
+  [task-name :- su/NonBlankString
    database  :- i/DatabaseInstance
    {:keys [start-time end-time]} :- SyncOperationOrStepRunMetadata]
   {:task       task-name
diff --git a/src/metabase/task/sync_databases.clj b/src/metabase/task/sync_databases.clj
index b753b06894296dcaabf4eb0b4c16b0d98133f78d..c915104a6efb34f814e9eadea76534fb15f155ca 100644
--- a/src/metabase/task/sync_databases.clj
+++ b/src/metabase/task/sync_databases.clj
@@ -34,7 +34,7 @@
 
 (declare unschedule-tasks-for-db!)
 
-(s/defn ^:private job-context->database-id :- (s/maybe su/IntGreaterThanZeroPlumatic)
+(s/defn ^:private job-context->database-id :- (s/maybe su/IntGreaterThanZero)
   "Get the Database ID referred to in `job-context`."
   [job-context]
   (u/the-id (get (qc/from-job-data job-context) "db-id")))
diff --git a/src/metabase/transforms/core.clj b/src/metabase/transforms/core.clj
index df0e38a2f5705da0c88c9e1d9b52c0cdc4cf445d..58c6f7ab86a1ba4cec867aec591166330b2e05e9 100644
--- a/src/metabase/transforms/core.clj
+++ b/src/metabase/transforms/core.clj
@@ -171,7 +171,7 @@
       (map first matches))))
 
 (s/defn ^:private tableset :- Tableset
-  [db-id :- su/IntGreaterThanZeroPlumatic, schema :- (s/maybe s/Str)]
+  [db-id :- su/IntGreaterThanZero, schema :- (s/maybe s/Str)]
   (table/with-fields
     (de/with-domain-entity
       (db/select 'Table :db_id db-id :schema schema))))
@@ -186,7 +186,7 @@
      cols to the bindings.
   4) Check that all output cards have the expected result shape.
   5) Return the output cards."
-  [db-id :- su/IntGreaterThanZeroPlumatic, schema :- (s/maybe s/Str), spec :- TransformSpec]
+  [db-id :- su/IntGreaterThanZero, schema :- (s/maybe s/Str), spec :- TransformSpec]
   (tf.materialize/fresh-collection-for-transform! spec)
   (some-> (tableset db-id schema)
           (tables-matching-requirements spec)
diff --git a/src/metabase/transforms/specs.clj b/src/metabase/transforms/specs.clj
index 218f49be41b0f92dab8523c68b28408e5b8b717d..4c9c83990953d2ef888ba488cb4bb0cea565e420 100644
--- a/src/metabase/transforms/specs.clj
+++ b/src/metabase/transforms/specs.clj
@@ -25,7 +25,7 @@
 
 (def ^:private Filter MBQL)
 
-(def ^:private Limit su/IntGreaterThanZeroPlumatic)
+(def ^:private Limit su/IntGreaterThanZero)
 
 (def ^:private Joins [{(s/required-key :source)    Source
                        (s/required-key :condition) MBQL
diff --git a/src/metabase/util/cron.clj b/src/metabase/util/cron.clj
index b4c94818ed03db6181047c9cbfccf9ae0bd1410c..b002e83fbca7abf618b50198231f0f632a640509 100644
--- a/src/metabase/util/cron.clj
+++ b/src/metabase/util/cron.clj
@@ -15,7 +15,7 @@
   "Schema for a valid cron schedule string."
   (su/with-api-error-message
       (s/constrained
-       su/NonBlankStringPlumatic
+       su/NonBlankString
        (fn [^String s]
          (try (CronExpression/validateExpression s)
               true
@@ -148,7 +148,7 @@
      :schedule_hour   (cron->digit hours)
      :schedule_type   (cron->schedule-type hours day-of-month day-of-week)}))
 
-(s/defn describe-cron-string :- su/NonBlankStringPlumatic
+(s/defn describe-cron-string :- su/NonBlankString
   "Return a human-readable description of a cron expression, localized for the current User."
   [cron-string :- CronScheduleString]
   (CronExpressionDescriptor/getDescription ^String cron-string, ^java.util.Locale (i18n/user-locale)))
diff --git a/src/metabase/util/honey_sql_1_extensions.clj b/src/metabase/util/honey_sql_1_extensions.clj
index 19bcc037d85568c872601253c22e0a03dab0d661..575d26244ed6f41de6eb7432d018a4e4c448d884 100644
--- a/src/metabase/util/honey_sql_1_extensions.clj
+++ b/src/metabase/util/honey_sql_1_extensions.clj
@@ -177,7 +177,7 @@
 (def ^:private NormalizedTypeInfo
   {(s/optional-key :metabase.util.honeysql-extensions/database-type)
    (s/constrained
-    su/NonBlankStringPlumatic
+    su/NonBlankString
     (fn [s]
       (= s (u/lower-case-en s)))
     "lowercased string")})
@@ -247,7 +247,7 @@
     (with-database-type-info :field \"text\")
     ;; -> #TypedHoneySQLForm{:form :field, :info {::hx/database-type \"text\"}}"
   {:style/indent [:form]}
-  [honeysql-form db-type :- (s/maybe su/KeywordOrStringPlumatic)]
+  [honeysql-form db-type :- (s/maybe su/KeywordOrString)]
   (if (some? db-type)
     (with-type-info honeysql-form {:metabase.util.honeysql-extensions/database-type db-type})
     (unwrap-typed-honeysql-form honeysql-form)))
diff --git a/src/metabase/util/honey_sql_2_extensions.clj b/src/metabase/util/honey_sql_2_extensions.clj
index aaeafe7e8f1964cb9fe9d98c7c0afa9efcc1cb72..43ad7f1afb200404e433db4c6602d3b8397a5bbc 100644
--- a/src/metabase/util/honey_sql_2_extensions.clj
+++ b/src/metabase/util/honey_sql_2_extensions.clj
@@ -9,7 +9,7 @@
    [honey.sql :as sql]
    [metabase.util :as u]
    [metabase.util.malli :as mu]
-   [metabase.util.schema :as su]
+   [metabase.util.malli.schema :as ms]
    [potemkin.types :as p.types])
   (:import
    (java.util Locale)))
@@ -177,7 +177,7 @@
    [:metabase.util.honeysql-extensions/database-type
     {:optional true}
     [:and
-     su/NonBlankString
+     ms/NonBlankString
      [:fn
       {:error/message "lowercased string"}
       (fn [s]
@@ -261,7 +261,7 @@
     (with-database-type-info :field \"text\")
     ;; -> #TypedHoneySQLForm{:form :field, :info {::hx/database-type \"text\"}}"
   {:style/indent [:form]}
-  [honeysql-form db-type :- [:maybe su/KeywordOrString]]
+  [honeysql-form db-type :- [:maybe ms/KeywordOrString]]
   (if (some? db-type)
     (with-type-info honeysql-form {:metabase.util.honeysql-extensions/database-type db-type})
     (unwrap-typed-honeysql-form honeysql-form)))
diff --git a/src/metabase/util/malli/schema.clj b/src/metabase/util/malli/schema.clj
new file mode 100644
index 0000000000000000000000000000000000000000..ea4dd23d5fe0dec75e4a70cf9cba317cab47cb93
--- /dev/null
+++ b/src/metabase/util/malli/schema.clj
@@ -0,0 +1,270 @@
+(ns metabase.util.malli.schema
+  (:require
+   [cheshire.core :as json]
+   [malli.core :as mc]
+   [metabase.mbql.normalize :as mbql.normalize]
+   [metabase.mbql.schema :as mbql.s]
+   [metabase.util :as u]
+   [metabase.util.date-2 :as u.date]
+   [metabase.util.i18n :as i18n :refer [deferred-tru]]
+   [metabase.util.password :as u.password]
+   [schema.core :as s]))
+
+(def NonBlankString
+  "Schema for a string that cannot be blank."
+  (mc/schema
+    [:string {:min 1}]))
+
+(def IntGreaterThanOrEqualToZero
+  "Schema representing an integer than must also be greater than or equal to zero."
+  (mc/schema
+    [:int {:min 0}]))
+
+;; TODO - rename this to `PositiveInt`?
+(def IntGreaterThanZero
+  "Schema representing an integer than must also be greater than zero."
+  (mc/schema
+    [:int {:min      1
+           :error/fn (constantly (deferred-tru "value must be an integer greater than zero."))}]))
+
+(def PositiveNum
+  "Schema representing a numeric value greater than zero. This allows floating point numbers and integers."
+  (mc/schema
+    [pos? {:error/fn (constantly (deferred-tru "value must be a number greater than zero."))}]))
+
+(def KeywordOrString
+  "Schema for something that can be either a `Keyword` or a `String`."
+  (mc/schema
+    [:or {:error/fn (constantly (deferred-tru "value must be a keyword or string."))}
+     :string :keyword]))
+
+(def FieldType
+  "Schema for a valid Field base or effective (data) type (does it derive from `:type/*`)?"
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field type."))}
+     #(isa? % :type/*)]))
+
+(def FieldSemanticType
+  "Schema for a valid Field semantic type deriving from `:Semantic/*`."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type."))}
+     #(isa? % :Semantic/*)]))
+
+(def FieldRelationType
+  "Schema for a valid Field relation type deriving from `:Relation/*`"
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type."))}
+     #(isa? % :Relation/*)]))
+
+(def FieldSemanticOrRelationType
+  "Schema for a valid Field semantic *or* Relation type. This is currently needed because the `semantic_column` is used
+  to store either the semantic type or relation type info. When this is changed in the future we can get rid of this
+  schema. See #15486."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type."))}
+     (fn [k] (or (isa? k :Semantic/*) (isa? k :Relation/*)))]))
+
+(def CoercionStrategy
+  "Schema for a valid Field coercion strategy (does it derive from `:Coercion/*`)?"
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy."))}
+     #(isa? % :Coercion/*)]))
+
+(def FieldTypeKeywordOrString
+  "Like `FieldType` (e.g. a valid derivative of `:type/*`) but allows either a keyword or a string.
+   This is useful especially for validating API input or objects coming out of the DB as it is unlikely
+   those values will be encoded as keywords at that point."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field data type (keyword or string)."))}
+     #(isa? (keyword %) :type/*)]))
+
+(def FieldSemanticTypeKeywordOrString
+  "Like `FieldSemanticType` but accepts either a keyword or string."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type (keyword or string)."))}
+     #(isa? (keyword %) :Semantic/*)]))
+
+(def FieldRelationTypeKeywordOrString
+  "Like `FieldRelationType` but accepts either a keyword or string."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type (keyword or string)."))}
+     #(isa? (keyword %) :Relation/*)]))
+
+(def FieldSemanticOrRelationTypeKeywordOrString
+  "Like `FieldSemanticOrRelationType` but accepts either a keyword or string."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type (keyword or string)."))}
+     (fn [k]
+       (let [k (keyword k)]
+         (or (isa? k :Semantic/*)
+             (isa? k :Relation/*))))]))
+
+(def Field
+  "Schema for a valid Field for API usage."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must an array with :field id-or-name and an options map"))}
+     (fn [k]
+       ((comp (complement (s/checker mbql.s/Field))
+              mbql.normalize/normalize-tokens) k))]))
+
+(def CoercionStrategyKeywordOrString
+  "Like `CoercionStrategy` but accepts either a keyword or string."
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy (keyword or string)."))}
+     #(isa? (keyword %) :Coercion/*)]))
+
+(def EntityTypeKeywordOrString
+  "Validates entity type derivatives of `:entity/*`. Allows strings or keywords"
+  (mc/schema
+    [:fn {:error/fn (constantly (deferred-tru "value must be a valid entity type (keyword or string)."))}
+     #(isa? (keyword %) :entity/*)]))
+
+(def Map
+  "Schema for a valid map."
+  (mc/schema
+    [:map {:error/fn (constantly (deferred-tru "Value must be a map."))}]))
+
+(def Email
+  "Schema for a valid email string."
+  (mc/schema
+    [:and
+     :string
+     [:fn {:error/fn (constantly (deferred-tru "value must be a valid email address."))}
+      u/email?]]))
+
+(def ValidPassword
+  "Schema for a valid password of sufficient complexity which is not found on a common password list."
+  (mc/schema
+    [:and
+     :string
+     [:fn {:error/fn (constantly (fn [_ _] (deferred-tru "password is too common.")))}
+      u.password/is-valid?]]))
+
+(def IntString
+  "Schema for a string that can be parsed as an integer.
+  Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
+  (mc/schema
+    [:and
+     :string
+     [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer."))}
+      #(u/ignore-exceptions (Integer/parseInt %))]]))
+
+(def IntStringGreaterThanZero
+  "Schema for a string that can be parsed as an integer, and is greater than zero.
+  Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
+  (mc/schema
+    [:and
+     :string
+     [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than zero."))}
+      #(u/ignore-exceptions (< 0 (Integer/parseInt %)))]]))
+
+(def IntStringGreaterThanOrEqualToZero
+  "Schema for a string that can be parsed as an integer, and is greater than or equal to zero.
+  Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
+  (mc/schema
+    [:and
+     :string
+     [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than or equal to zero."))}
+      #(u/ignore-exceptions (<= 0 (Integer/parseInt %)))]]))
+
+(def BooleanString
+  "Schema for a string that is a valid representation of a boolean (either `true` or `false`).
+  Something that adheres to this schema is guaranteed to to work with `Boolean/parseBoolean`."
+  (mc/schema
+    [:enum "true" "false"]))
+
+(def TemporalString
+  "Schema for a string that can be parsed by date2/parse."
+  (mc/schema
+    [:and
+     :string
+     [:fn {:error/fn (constantly (deferred-tru "value must be a valid date string"))}
+      #(u/ignore-exceptions (boolean (u.date/parse %)))]]))
+
+(def JSONString
+  "Schema for a string that is valid serialized JSON."
+  (mc/schema
+    [:and
+     :string
+     [:fn {:error/fn (constantly (deferred-tru "value must be a valid JSON string."))}
+      #(try
+         (json/parse-string %)
+         true
+         (catch Throwable _
+           false))]]))
+
+(def ^:private keyword-or-non-blank-str-malli
+  (mc/schema
+    [:or :keyword NonBlankString]))
+
+(def ValuesSourceConfig
+  "Schema for valid source_options within a Parameter"
+  ;; TODO: This should be tighter
+  (mc/schema
+    [:map
+     [:values {:optional true} [:* :any]]
+     [:card_id {:optional true} IntGreaterThanZero]
+     [:value_field {:optional true} Field]
+     [:label_field {:optional true} Field]]))
+
+#_(def ParameterSource
+      (mc/schema
+        [:multi {:dispatch :values_source_type}
+         ["card"        [:map
+                         [:values_source_type :string]
+                         [:values_source_config
+                          [:map {:closed true}
+                           [:card_id {:optional true} IntGreaterThanZero]
+                           [:value_field {:optional true} Field]
+                           [:label_field {:optional true} Field]]]]]
+         ["static-list" [:map
+                         [:values_source_type :string]
+                         [:values_source_config
+                          [:map {:closed true}
+                           [:values {:optional true} [:* :any]]]]]]]))
+
+(def Parameter
+  "Schema for a valid Parameter.
+  We're not using [metabase.mbql.schema/Parameter] here because this Parameter is meant to be used for
+  Parameters we store on dashboard/card, and it has some difference with Parameter in MBQL."
+  ;; TODO we could use :multi to dispatch values_source_type to the correct values_source_config
+  (mc/schema
+    [:map {:error/fn (constantly (deferred-tru "parameter must be a map with :id and :type keys"))}
+     [:id NonBlankString]
+     [:type keyword-or-non-blank-str-malli]
+     ;; TODO how to merge this with ParameterSource above?
+     [:values_source_type {:optional true} [:enum "static-list" "card" nil]]
+     [:values_source_config {:optional true} ValuesSourceConfig]
+     [:slug {:optional true} :string]
+     [:name {:optional true} :string]
+     [:default {:optional true} :any]
+     [:sectionId {:optional true} NonBlankString]]))
+
+(def ParameterMapping
+  "Schema for a valid Parameter Mapping"
+  (mc/schema
+    [:map {:error/fn (constantly (deferred-tru "parameter_mapping must be a map with :parameter_id and :target keys"))}
+     [:parameter_id NonBlankString]
+     [:target :any]
+     [:card_id {:optional true} IntGreaterThanZero]]))
+
+(def EmbeddingParams
+  "Schema for a valid map of embedding params."
+  (mc/schema
+    [:map-of {:error/fn (constantly (deferred-tru "value must be a valid embedding params map."))}
+     :keyword
+     [:enum "disabled" "enabled" "locked"]]))
+
+(def ValidLocale
+  "Schema for a valid ISO Locale code e.g. `en` or `en-US`. Case-insensitive and allows dashes or underscores."
+  (mc/schema
+    [:and
+     NonBlankString
+     [:fn {:error/fn (constantly (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'."))}
+      i18n/available-locale?]]))
+
+(def NanoIdString
+  "Schema for a 21-character NanoID string, like \"FReCLx5hSWTBU7kjCWfuu\"."
+  (mc/schema
+    [:re {:error/fn (constantly (deferred-tru "String must be a valid 21-character NanoID string."))}
+     #"^[A-Za-z0-9_\-]{21}$"]))
diff --git a/src/metabase/util/schema.clj b/src/metabase/util/schema.clj
index 8abb7fa93bcfc4f62ee5bb80a5abc647a58faa34..d36fab91b192c9fa11014fade594365b5d5df002 100644
--- a/src/metabase/util/schema.clj
+++ b/src/metabase/util/schema.clj
@@ -1,11 +1,13 @@
-(ns metabase.util.schema
-  "Various schemas that are useful throughout the app."
+(ns ^{:deprecated "0.46.0"} metabase.util.schema
+  "Various schemas that are useful throughout the app.
+
+  Schemas defined are deprecated and should be replaced with Malli schema defined in [[metabase.util.malli.schema]].
+  If you update schemas in this ns, please make sure you update the malli schema too. It'll help us makes the transition easier."
   (:refer-clojure :exclude [distinct])
   (:require
    [cheshire.core :as json]
    [clojure.string :as str]
    [clojure.walk :as walk]
-   [malli.core :as mc]
    [medley.core :as m]
    [metabase.mbql.normalize :as mbql.normalize]
    [metabase.mbql.schema :as mbql.s]
@@ -199,98 +201,53 @@
 ;;; |                                                 USEFUL SCHEMAS                                                 |
 ;;; +----------------------------------------------------------------------------------------------------------------+
 
-(def NonBlankStringPlumatic
+(def NonBlankString
   "Schema for a string that cannot be blank."
   (with-api-error-message (s/constrained s/Str (complement str/blank?) "Non-blank string")
     (deferred-tru "value must be a non-blank string.")))
 
-(def NonBlankString
-  "Schema for a string that cannot be blank."
-  (mc/schema
-    [:string {:min 1}]))
-
-(def IntGreaterThanOrEqualToZeroPlumatic
+(def IntGreaterThanOrEqualToZero
   "Schema representing an integer than must also be greater than or equal to zero."
   (with-api-error-message
     (s/constrained s/Int (partial <= 0) (deferred-tru "Integer greater than or equal to zero"))
     (deferred-tru "value must be an integer greater than or equal to zero.")))
 
-(def IntGreaterThanOrEqualToZero
-  "Schema representing an integer than must also be greater than or equal to zero."
-  (mc/schema
-    [:int {:min 0}]))
-
 ;; TODO - rename this to `PositiveInt`?
-(def IntGreaterThanZeroPlumatic
+(def IntGreaterThanZero
   "Schema representing an integer than must also be greater than zero."
   (with-api-error-message
     (s/constrained s/Int (partial < 0) (deferred-tru "Integer greater than zero"))
     (deferred-tru "value must be an integer greater than zero.")))
 
-(def IntGreaterThanZero
-  "Schema representing an integer than must also be greater than zero."
-  (mc/schema
-    [:int {:min      1
-           :error/fn (constantly (deferred-tru "value must be an integer greater than zero."))}]))
-
-(def PositiveNumPlumatic
+(def PositiveNum
   "Schema representing a numeric value greater than zero. This allows floating point numbers and integers."
   (with-api-error-message
     (s/constrained s/Num (partial < 0) (deferred-tru "Number greater than zero"))
     (deferred-tru "value must be a number greater than zero.")))
 
-(def PositiveNum
-  "Schema representing a numeric value greater than zero. This allows floating point numbers and integers."
-  (mc/schema
-    [pos? {:error/fn (constantly (deferred-tru "value must be a number greater than zero."))}]))
-
-(def KeywordOrStringPlumatic
+(def KeywordOrString
   "Schema for something that can be either a `Keyword` or a `String`."
   (with-api-error-message (s/named (s/cond-pre s/Keyword s/Str) (deferred-tru "Keyword or string"))
     (deferred-tru "value must be a keyword or string.")))
 
-(def KeywordOrString
-  "Schema for something that can be either a `Keyword` or a `String`."
-  (mc/schema
-    [:or {:error/fn (constantly (deferred-tru "value must be a keyword or string."))}
-     :string :keyword]))
-
-(def FieldTypePlumatic
+(def FieldType
   "Schema for a valid Field base or effective (data) type (does it derive from `:type/*`)?"
   (with-api-error-message (s/pred #(isa? % :type/*) (deferred-tru "Valid field type"))
     (deferred-tru "value must be a valid field type.")))
 
-(def FieldType
-  "Schema for a valid Field base or effective (data) type (does it derive from `:type/*`)?"
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field type."))}
-     #(isa? % :type/*)]))
-
-(def FieldSemanticTypePlumatic
+(def FieldSemanticType
   "Schema for a valid Field semantic type deriving from `:Semantic/*`."
   (with-api-error-message (s/pred #(isa? % :Semantic/*)
                                   (deferred-tru "Valid field semantic type"))
     (deferred-tru "value must be a valid field semantic type.")))
 
-(def FieldSemanticType
-  "Schema for a valid Field semantic type deriving from `:Semantic/*`."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type."))}
-     #(isa? % :Semantic/*)]))
-
-(def FieldRelationTypePlumatic
+(def FieldRelationType
   "Schema for a valid Field relation type deriving from `:Relation/*`"
   (with-api-error-message (s/pred #(isa? % :Relation/*)
                                   (deferred-tru "Valid field relation type"))
     (deferred-tru "value must be a valid field relation type.")))
 
-(def FieldRelationType
-  "Schema for a valid Field relation type deriving from `:Relation/*`"
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type."))}
-     #(isa? % :Relation/*)]))
-
-(def FieldSemanticOrRelationTypePlumatic
+(def FieldSemanticOrRelationType
   "Schema for a valid Field semantic *or* Relation type. This is currently needed because the `semantic_column` is used
   to store either the semantic type or relation type info. When this is changed in the future we can get rid of this
   schema. See #15486."
@@ -300,63 +257,29 @@
                                   (deferred-tru "Valid field semantic or relation type"))
     (deferred-tru "value must be a valid field semantic or relation type.")))
 
-(def FieldSemanticOrRelationType
-  "Schema for a valid Field semantic *or* Relation type. This is currently needed because the `semantic_column` is used
-  to store either the semantic type or relation type info. When this is changed in the future we can get rid of this
-  schema. See #15486."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type."))}
-     (fn [k] (or (isa? k :Semantic/*) (isa? k :Relation/*)))]))
-
-(def CoercionStrategyPlumatic
+(def CoercionStrategy
   "Schema for a valid Field coercion strategy (does it derive from `:Coercion/*`)?"
   (with-api-error-message (s/pred #(isa? % :Coercion/*) (deferred-tru "Valid coercion strategy"))
     (deferred-tru "value must be a valid coercion strategy.")))
 
-(def CoercionStrategy
-  "Schema for a valid Field coercion strategy (does it derive from `:Coercion/*`)?"
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy."))}
-     #(isa? % :Coercion/*)]))
-
-(def FieldTypeKeywordOrStringPlumatic
+(def FieldTypeKeywordOrString
   "Like `FieldType` (e.g. a valid derivative of `:type/*`) but allows either a keyword or a string.
    This is useful especially for validating API input or objects coming out of the DB as it is unlikely
    those values will be encoded as keywords at that point."
   (with-api-error-message (s/pred #(isa? (keyword %) :type/*) (deferred-tru "Valid field data type (keyword or string)"))
     (deferred-tru "value must be a valid field data type (keyword or string).")))
 
-(def FieldTypeKeywordOrString
-  "Like `FieldType` (e.g. a valid derivative of `:type/*`) but allows either a keyword or a string.
-   This is useful especially for validating API input or objects coming out of the DB as it is unlikely
-   those values will be encoded as keywords at that point."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field data type (keyword or string)."))}
-     #(isa? (keyword %) :type/*)]))
-
-(def FieldSemanticTypeKeywordOrStringPlumatic
+(def FieldSemanticTypeKeywordOrString
   "Like `FieldSemanticType` but accepts either a keyword or string."
   (with-api-error-message (s/pred #(isa? (keyword %) :Semantic/*) (deferred-tru "Valid field semantic type (keyword or string)"))
     (deferred-tru "value must be a valid field semantic type (keyword or string).")))
 
-(def FieldSemanticTypeKeywordOrString
-  "Like `FieldSemanticType` but accepts either a keyword or string."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type (keyword or string)."))}
-     #(isa? (keyword %) :Semantic/*)]))
-
-(def FieldRelationTypeKeywordOrStringPlumatic
+(def FieldRelationTypeKeywordOrString
   "Like `FieldRelationType` but accepts either a keyword or string."
   (with-api-error-message (s/pred #(isa? (keyword %) :Relation/*) (deferred-tru "Valid field relation type (keyword or string)"))
     (deferred-tru "value must be a valid field relation type (keyword or string).")))
 
-(def FieldRelationTypeKeywordOrString
-  "Like `FieldRelationType` but accepts either a keyword or string."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type (keyword or string)."))}
-     #(isa? (keyword %) :Relation/*)]))
-
-(def FieldSemanticOrRelationTypeKeywordOrStringPlumatic
+(def FieldSemanticOrRelationTypeKeywordOrString
   "Like `FieldSemanticOrRelationType` but accepts either a keyword or string."
   (with-api-error-message (s/pred (fn [k]
                                     (let [k (keyword k)]
@@ -365,167 +288,73 @@
                                   (deferred-tru "Valid field semantic or relation type (keyword or string)"))
     (deferred-tru "value must be a valid field semantic or relation type (keyword or string).")))
 
-(def FieldSemanticOrRelationTypeKeywordOrString
-  "Like `FieldSemanticOrRelationType` but accepts either a keyword or string."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type (keyword or string)."))}
-     (fn [k]
-       (let [k (keyword k)]
-         (or (isa? k :Semantic/*)
-             (isa? k :Relation/*))))]))
-
-(def FieldPlumatic
+(def Field
   "Schema for a valid Field for API usage."
   (with-api-error-message (s/pred
                             (comp (complement (s/checker mbql.s/Field))
                                   mbql.normalize/normalize-tokens))
     (deferred-tru "value must an array with :field id-or-name and an options map")))
 
-(def Field
-  "Schema for a valid Field for API usage."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must an array with :field id-or-name and an options map"))}
-     (fn [k]
-       ((comp (complement (s/checker mbql.s/Field))
-              mbql.normalize/normalize-tokens) k))]))
-
-(def CoercionStrategyKeywordOrStringPlumatic
+(def CoercionStrategyKeywordOrString
   "Like `CoercionStrategy` but accepts either a keyword or string."
   (with-api-error-message (s/pred #(isa? (keyword %) :Coercion/*) (deferred-tru "Valid coercion strategy"))
     (deferred-tru "value must be a valid coercion strategy (keyword or string).")))
 
-(def CoercionStrategyKeywordOrString
-  "Like `CoercionStrategy` but accepts either a keyword or string."
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy (keyword or string)."))}
-     #(isa? (keyword %) :Coercion/*)]))
-
-(def EntityTypeKeywordOrStringPlumatic
+(def EntityTypeKeywordOrString
   "Validates entity type derivatives of `:entity/*`. Allows strings or keywords"
   (with-api-error-message (s/pred #(isa? (keyword %) :entity/*) (deferred-tru "Valid entity type (keyword or string)"))
     (deferred-tru "value must be a valid entity type (keyword or string).")))
 
-(def EntityTypeKeywordOrString
-  "Validates entity type derivatives of `:entity/*`. Allows strings or keywords"
-  (mc/schema
-    [:fn {:error/fn (constantly (deferred-tru "value must be a valid entity type (keyword or string)."))}
-     #(isa? (keyword %) :entity/*)]))
-
-(def MapPlumatic
+(def Map
   "Schema for a valid map."
   (with-api-error-message (s/named clojure.lang.IPersistentMap (deferred-tru "Valid map"))
     (deferred-tru "value must be a map.")))
 
-(def Map
-  "Schema for a valid map."
-  (mc/schema
-    [:map {:error/fn (constantly (deferred-tru "Value must be a map."))}]))
-
-(def EmailPlumatic
+(def Email
   "Schema for a valid email string."
   (with-api-error-message (s/constrained s/Str u/email? (deferred-tru "Valid email address"))
     (deferred-tru "value must be a valid email address.")))
 
-(def Email
-  "Schema for a valid email string."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (deferred-tru "value must be a valid email address."))}
-      u/email?]]))
-
-(def ValidPasswordPlumatic
+(def ValidPassword
   "Schema for a valid password of sufficient complexity which is not found on a common password list."
   (with-api-error-message (s/constrained s/Str u.password/is-valid?)
     (deferred-tru "password is too common.")))
 
-(def ValidPassword
-  "Schema for a valid password of sufficient complexity which is not found on a common password list."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (fn [_ _] (deferred-tru "password is too common.")))}
-      u.password/is-valid?]]))
-
-(def IntStringPlumatic
+(def IntString
   "Schema for a string that can be parsed as an integer.
    Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
   (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (Integer/parseInt %)))
     (deferred-tru "value must be a valid integer.")))
 
-(def IntString
-  "Schema for a string that can be parsed as an integer.
-  Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer."))}
-      #(u/ignore-exceptions (Integer/parseInt %))]]))
-
-(def IntStringGreaterThanZeroPlumatic
+(def IntStringGreaterThanZero
   "Schema for a string that can be parsed as an integer, and is greater than zero.
    Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
   (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (< 0 (Integer/parseInt %))))
     (deferred-tru "value must be a valid integer greater than zero.")))
 
-(def IntStringGreaterThanZero
-  "Schema for a string that can be parsed as an integer, and is greater than zero.
-  Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than zero."))}
-      #(u/ignore-exceptions (< 0 (Integer/parseInt %)))]]))
-
-(def IntStringGreaterThanOrEqualToZeroPlumatic
+(def IntStringGreaterThanOrEqualToZero
   "Schema for a string that can be parsed as an integer, and is greater than or equal to zero.
    Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
   (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (<= 0 (Integer/parseInt %))))
     (deferred-tru "value must be a valid integer greater than or equal to zero.")))
 
-(def IntStringGreaterThanOrEqualToZero
-  "Schema for a string that can be parsed as an integer, and is greater than or equal to zero.
-  Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than or equal to zero."))}
-      #(u/ignore-exceptions (<= 0 (Integer/parseInt %)))]]))
-
 (defn- boolean-string? ^Boolean [s]
   (boolean (when (string? s)
              (let [s (u/lower-case-en s)]
                (contains? #{"true" "false"} s)))))
 
-(def BooleanStringPlumatic
+(def BooleanString
   "Schema for a string that is a valid representation of a boolean (either `true` or `false`).
    Something that adheres to this schema is guaranteed to to work with `Boolean/parseBoolean`."
   (with-api-error-message (s/constrained s/Str boolean-string?)
     (deferred-tru "value must be a valid boolean string (''true'' or ''false'').")))
 
-(def BooleanString
-  "Schema for a string that is a valid representation of a boolean (either `true` or `false`).
-  Something that adheres to this schema is guaranteed to to work with `Boolean/parseBoolean`."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (deferred-tru "value must be a valid boolean string (''true'' or ''false'')."))}
-      boolean-string?]]))
-
-(def TemporalStringPlumatic
+(def TemporalString
   "Schema for a string that can be parsed by date2/parse."
   (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (boolean (u.date/parse %))))
     (deferred-tru "value must be a valid date string")))
 
-(def TemporalString
-  "Schema for a string that can be parsed by date2/parse."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (deferred-tru "value must be a valid date string"))}
-      #(u/ignore-exceptions (boolean (u.date/parse %)))]]))
-
-(def JSONStringPlumatic
+(def JSONString
   "Schema for a string that is valid serialized JSON."
   (with-api-error-message (s/constrained s/Str #(try
                                                   (json/parse-string %)
@@ -534,145 +363,58 @@
                                                     false)))
     (deferred-tru "value must be a valid JSON string.")))
 
-(def JSONString
-  "Schema for a string that is valid serialized JSON."
-  (mc/schema
-    [:and
-     :string
-     [:fn {:error/fn (constantly (deferred-tru "value must be a valid JSON string."))}
-      #(try
-         (json/parse-string %)
-         true
-         (catch Throwable _
-           false))]]))
-
 (def ^:private keyword-or-non-blank-str
   (s/conditional
-    string?  NonBlankStringPlumatic
+    string?  NonBlankString
     keyword? s/Keyword))
 
-(def ^:private keyword-or-non-blank-str-malli
-  (mc/schema
-    [:or :keyword NonBlankString]))
-
-(def ValuesSourceConfigPlumatic
+(def ValuesSourceConfig
   "Schema for valid source_options within a Parameter"
   ;; TODO: This should be tighter
   {;; for source_type = 'static-list'
    (s/optional-key :values)      (s/cond-pre [s/Any])
 
    ;; for source_type = 'card'
-   (s/optional-key :card_id)     IntGreaterThanZeroPlumatic
-   (s/optional-key :value_field) FieldPlumatic
+   (s/optional-key :card_id)     IntGreaterThanZero
+   (s/optional-key :value_field) Field
    ;; label_field is optional
-   (s/optional-key :label_field) FieldPlumatic})
+   (s/optional-key :label_field) Field})
 
-(def ValuesSourceConfig
-  "Schema for valid source_options within a Parameter"
-  (mc/schema
-    [:map
-     [:values {:optional true} [:* :any]]
-     [:card_id {:optional true} IntGreaterThanZero]
-     [:value_field {:optional true} Field]
-     [:label_field {:optional true} Field]]))
-
-(def ParameterPlumatic
+(def Parameter
   "Schema for a valid Parameter.
   We're not using [metabase.mbql.schema/Parameter] here because this Parameter is meant to be used for
   Parameters we store on dashboard/card, and it has some difference with Parameter in MBQL."
-  (with-api-error-message {:id                                    NonBlankStringPlumatic
+  (with-api-error-message {:id                                    NonBlankString
                            :type                                  keyword-or-non-blank-str
                            (s/optional-key :values_source_type)   (s/enum "static-list" "card" nil)
-                           (s/optional-key :values_source_config) ValuesSourceConfigPlumatic
+                           (s/optional-key :values_source_config) ValuesSourceConfig
                            ;; Allow blank name and slug #15279
                            (s/optional-key :slug)                 s/Str
                            (s/optional-key :name)                 s/Str
                            (s/optional-key :default)              s/Any
-                           (s/optional-key :sectionId)            NonBlankStringPlumatic
+                           (s/optional-key :sectionId)            NonBlankString
                            s/Keyword                              s/Any}
     (deferred-tru "parameter must be a map with :id and :type keys")))
 
-#_(def ParameterSource
-    (mc/schema
-      [:multi {:dispatch :values_source_type}
-       ["card"        [:map
-                       [:values_source_type :string]
-                       [:values_source_config
-                        [:map {:closed true}
-                         [:card_id {:optional true} IntGreaterThanZero]
-                         [:value_field {:optional true} Field]
-                         [:label_field {:optional true} Field]]]]]
-       ["static-list" [:map
-                       [:values_source_type :string]
-                       [:values_source_config
-                        [:map {:closed true}
-                         [:values {:optional true} [:* :any]]]]]]]))
-
-(def Parameter
-  "Schema for a valid Parameter.
-  We're not using [metabase.mbql.schema/Parameter] here because this Parameter is meant to be used for
-  Parameters we store on dashboard/card, and it has some difference with Parameter in MBQL."
-  ;; TODO we could use :multi to dispatch values_source_type to the correct values_source_config
-  (mc/schema
-    [:map {:error/fn (constantly (deferred-tru "parameter must be a map with :id and :type keys"))}
-     [:id NonBlankString]
-     [:type keyword-or-non-blank-str-malli]
-     ;; TODO how to merge this with ParameterSource above?
-     [:values_source_type {:optional true} [:enum "static-list" "card" nil]]
-     [:values_source_config {:optional true} ValuesSourceConfig]
-     [:slug {:optional true} :string]
-     [:name {:optional true} :string]
-     [:default {:optional true} :any]
-     [:sectionId {:optional true} NonBlankString]]))
-
-(def ParameterMappingPlumatic
+(def ParameterMapping
   "Schema for a valid Parameter Mapping"
-  (with-api-error-message {:parameter_id             NonBlankStringPlumatic
+  (with-api-error-message {:parameter_id             NonBlankString
                            :target                   s/Any
-                           (s/optional-key :card_id) IntGreaterThanZeroPlumatic
+                           (s/optional-key :card_id) IntGreaterThanZero
                            s/Keyword                 s/Any}
     (deferred-tru "parameter_mapping must be a map with :parameter_id and :target keys")))
 
-(def ParameterMapping
-  "Schema for a valid Parameter Mapping"
-  (mc/schema
-    [:map {:error/fn (constantly (deferred-tru "parameter_mapping must be a map with :parameter_id and :target keys"))}
-     [:parameter_id NonBlankString]
-     [:target :any]
-     [:card_id {:optional true} IntGreaterThanZero]]))
-
-(def EmbeddingParamsPlumatic
+(def EmbeddingParams
   "Schema for a valid map of embedding params."
   (with-api-error-message (s/maybe {s/Keyword (s/enum "disabled" "enabled" "locked")})
     (deferred-tru "value must be a valid embedding params map.")))
 
-(def EmbeddingParams
-  "Schema for a valid map of embedding params."
-  (mc/schema
-    [:map-of {:error/fn (constantly (deferred-tru "value must be a valid embedding params map."))}
-     :keyword
-     [:enum "disabled" "enabled" "locked"]]))
-
-(def ValidLocalePlumatic
-  "Schema for a valid ISO Locale code e.g. `en` or `en-US`. Case-insensitive and allows dashes or underscores."
-  (with-api-error-message (s/constrained NonBlankStringPlumatic i18n/available-locale?)
-    (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'.")))
-
 (def ValidLocale
   "Schema for a valid ISO Locale code e.g. `en` or `en-US`. Case-insensitive and allows dashes or underscores."
-  (mc/schema
-    [:and
-     NonBlankString
-     [:fn {:error/fn (constantly (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'."))}
-      i18n/available-locale?]]))
+  (with-api-error-message (s/constrained NonBlankString i18n/available-locale?)
+    (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'.")))
 
-(def NanoIdStringPlumatic
+(def NanoIdString
   "Schema for a 21-character NanoID string, like \"FReCLx5hSWTBU7kjCWfuu\"."
   (with-api-error-message #"^[A-Za-z0-9_\-]{21}$"
     (deferred-tru "String must be a valid 21-character NanoID string.")))
-
-(def NanoIdString
-  "Schema for a 21-character NanoID string, like \"FReCLx5hSWTBU7kjCWfuu\"."
-  (mc/schema
-    [:re {:error/fn (constantly (deferred-tru "String must be a valid 21-character NanoID string."))}
-     #"^[A-Za-z0-9_\-]{21}$"]))
diff --git a/test/metabase/actions_test.clj b/test/metabase/actions_test.clj
index 17bbae1015cf1dd562c808722e5f8050f2bc7a84..546f9351ddf58424ea4d1203b3974958be31427f 100644
--- a/test/metabase/actions_test.clj
+++ b/test/metabase/actions_test.clj
@@ -110,8 +110,8 @@
     :request-body (assoc (mt/mbql-query categories) :create-row {(format-field-name :name) "created_row"})
     :expect-fn    (fn [result]
                     ;; check that we return the entire row
-                    (is (schema= {:created-row {(format-field-name :id)   su/IntGreaterThanZeroPlumatic
-                                                (format-field-name :name) su/NonBlankStringPlumatic}}
+                    (is (schema= {:created-row {(format-field-name :id)   su/IntGreaterThanZero
+                                                (format-field-name :name) su/NonBlankString}}
                                  result)))}
    {:action       :row/update
     :request-body (assoc (mt/mbql-query categories {:filter [:= $id 1]})
diff --git a/test/metabase/analytics/stats_test.clj b/test/metabase/analytics/stats_test.clj
index 21e9e802b20f662e0d5a347443dbd74bacc6edb0..bfce9779514bf0f31310768852a8e8d75ebec4d0 100644
--- a/test/metabase/analytics/stats_test.clj
+++ b/test/metabase/analytics/stats_test.clj
@@ -69,7 +69,7 @@
     "10000+"     100000))
 
 (def DBMSVersionStats
-  {s/Str su/IntGreaterThanOrEqualToZeroPlumatic})
+  {s/Str su/IntGreaterThanOrEqualToZero})
 
 (deftest anonymous-usage-stats-test
   (with-redefs [email/email-configured? (constantly false)
diff --git a/test/metabase/api/action_test.clj b/test/metabase/api/action_test.clj
index 4702fb914e691dee02931ae640cb73b3e562935d..ed2f7bf9d24aad284eaffa229fc4596ab304bf36 100644
--- a/test/metabase/api/action_test.clj
+++ b/test/metabase/api/action_test.clj
@@ -13,18 +13,18 @@
 
 (def ^:private ExpectedGetQueryActionAPIResponse
   "Expected schema for a query action as it should appear in the response for an API request to one of the GET endpoints."
-  {:id                     su/IntGreaterThanOrEqualToZeroPlumatic
+  {:id                     su/IntGreaterThanOrEqualToZero
    :type                   (s/eq "query")
-   :model_id               su/IntGreaterThanOrEqualToZeroPlumatic
-   :database_id            su/IntGreaterThanOrEqualToZeroPlumatic
-   :dataset_query          {:database su/IntGreaterThanOrEqualToZeroPlumatic
+   :model_id               su/IntGreaterThanOrEqualToZero
+   :database_id            su/IntGreaterThanOrEqualToZero
+   :dataset_query          {:database su/IntGreaterThanOrEqualToZero
                             :type     (s/eq "native")
                             :native   {:query    s/Str
                                        s/Keyword s/Any}
                             s/Keyword s/Any}
    :parameters             s/Any
    :parameter_mappings     s/Any
-   :visualization_settings su/MapPlumatic
+   :visualization_settings su/Map
    s/Keyword               s/Any})
 
 (deftest list-actions-test
diff --git a/test/metabase/api/card_test.clj b/test/metabase/api/card_test.clj
index 5788d132f8e2ed5dc4268e79765178585a8e01d3..e9067d7da572ee361b7910be13b9e4bb2034b9c3 100644
--- a/test/metabase/api/card_test.clj
+++ b/test/metabase/api/card_test.clj
@@ -499,7 +499,7 @@
         (testing query-description
           (mt/with-model-cleanup [Card]
             (testing "without result metadata"
-              (is (schema= {:id       su/IntGreaterThanZeroPlumatic
+              (is (schema= {:id       su/IntGreaterThanZero
                             s/Keyword s/Any}
                            (mt/user-http-request :rasta :post 200 "card"
                                                  (merge (mt/with-temp-defaults Card)
@@ -510,7 +510,7 @@
                                :columns)]
               (testing (format "with result metadata\n%s" (u/pprint-to-str metadata))
                 (is (some? metadata))
-                (is (schema= {:id       su/IntGreaterThanZeroPlumatic
+                (is (schema= {:id       su/IntGreaterThanZero
                               s/Keyword s/Any}
                              (mt/user-http-request :rasta :post 200 "card"
                                                    (merge (mt/with-temp-defaults Card)
@@ -521,7 +521,7 @@
   (testing "we should be able to save a Card if the `result_metadata` is *empty* (but not nil) (#9286)"
     (mt/with-model-cleanup [Card]
       (let [card        (card-with-name-and-query)]
-        (is (schema= {:id su/IntGreaterThanZeroPlumatic, s/Keyword s/Any}
+        (is (schema= {:id su/IntGreaterThanZero, s/Keyword s/Any}
                      (mt/user-http-request :rasta
                                            :post
                                            200
diff --git a/test/metabase/api/collection_test.clj b/test/metabase/api/collection_test.clj
index 53f489b9e5620087579639b2452f32c488667d59..95696bb44407f4012d840d93fe5bf278751ec49b 100644
--- a/test/metabase/api/collection_test.clj
+++ b/test/metabase/api/collection_test.clj
@@ -1349,7 +1349,7 @@
                         :authority_level   (s/eq "official")
                         :id                s/Int
                         :location          (s/eq "/")
-                        :entity_id         (s/maybe su/NanoIdStringPlumatic)
+                        :entity_id         (s/maybe su/NanoIdString)
                         :namespace         (s/eq nil)
                         :created_at        java.time.temporal.Temporal}
                        (mt/user-http-request :crowberto :post 200 "collection"
diff --git a/test/metabase/api/database_test.clj b/test/metabase/api/database_test.clj
index 6b1970bbeb5bb725cd563d6680f4df16114884c6..75ec9eacf039751565d8af5a260dedc74e742b76 100644
--- a/test/metabase/api/database_test.clj
+++ b/test/metabase/api/database_test.clj
@@ -180,10 +180,10 @@
                      :cache_field_values_schedule #"0 \d{1,2} \d{1,2} \* \* \? \*"}
                     {:created_at java.time.temporal.Temporal
                      :engine     (s/eq ::test-driver)
-                     :id         su/IntGreaterThanZeroPlumatic
+                     :id         su/IntGreaterThanZero
                      :details    (s/eq {:db "my_db"})
                      :updated_at java.time.temporal.Temporal
-                     :name       su/NonBlankStringPlumatic
+                     :name       su/NonBlankString
                      :features   (s/eq (driver.u/features ::test-driver (mt/db)))
                      :creator_id (s/eq (mt/user->id :crowberto))})
                    (create-db-via-api!))))
@@ -659,7 +659,7 @@
                                             :moderated_status (s/enum nil "verified")
                                             :schema           s/Str ; collection name
                                             :description      (s/maybe s/Str)
-                                            :fields           [su/MapPlumatic]}]}
+                                            :fields           [su/Map]}]}
                      response))
         (check-tables-included
          response
diff --git a/test/metabase/api/dataset_test.clj b/test/metabase/api/dataset_test.clj
index 1d1c5f21bc5c367fdd68d69c60d991fc66af364e..4cc8512e87486fb6b575fa4ecf68c534f67963fd 100644
--- a/test/metabase/api/dataset_test.clj
+++ b/test/metabase/api/dataset_test.clj
@@ -139,7 +139,7 @@
 
         (testing "\nSaved QueryExecution"
           (is (schema= {:hash         (Class/forName "[B")
-                        :id           su/IntGreaterThanZeroPlumatic
+                        :id           su/IntGreaterThanZero
                         :result_rows  (s/eq 0)
                         :row_count    (s/eq 0)
                         :context      (s/eq :ad-hoc)
diff --git a/test/metabase/api/geojson_test.clj b/test/metabase/api/geojson_test.clj
index 02c2f95a4521f8232cb5be35d66712321d70d5d7..b997d0c112ecb11afbe7720521a241ea67a2b0ad 100644
--- a/test/metabase/api/geojson_test.clj
+++ b/test/metabase/api/geojson_test.clj
@@ -188,7 +188,7 @@
                             :value          (s/eq nil)
                             :is_env_setting (s/eq true)
                             :env_name       (s/eq "MB_CUSTOM_GEOJSON")
-                            :description    su/NonBlankStringPlumatic
+                            :description    su/NonBlankString
                             :default        (s/eq "Using value of env var $MB_CUSTOM_GEOJSON")
                             s/Keyword       s/Any}
                            (some
diff --git a/test/metabase/api/native_query_snippet_test.clj b/test/metabase/api/native_query_snippet_test.clj
index e003ff7c801033ce6b595254e96b7e7081d90ecc..d6ad35356fa21e9697d5f9fb8e97a4cb4525025c 100644
--- a/test/metabase/api/native_query_snippet_test.clj
+++ b/test/metabase/api/native_query_snippet_test.clj
@@ -74,7 +74,7 @@
         (try
           (let [snippet-input    {:name "test-snippet", :description "Just null", :content "NULL"}
                 snippet-from-api (mt/user-http-request user :post 200 (snippet-url) snippet-input)]
-            (is (schema= {:id          su/IntGreaterThanZeroPlumatic
+            (is (schema= {:id          su/IntGreaterThanZero
                           :name        (s/eq "test-snippet")
                           :description (s/eq "Just null")
                           :content     (s/eq "NULL")
diff --git a/test/metabase/api/permissions_test.clj b/test/metabase/api/permissions_test.clj
index 8a4de348d4cf0026ebb63ec64097fb28968f0b70..e050d58ea84aa6518cc45167ae4bd1139d006f22 100644
--- a/test/metabase/api/permissions_test.clj
+++ b/test/metabase/api/permissions_test.clj
@@ -37,12 +37,12 @@
               (testing "All Users Group should be returned"
                 (is (schema= {:id           (s/eq (:id (perms-group/all-users)))
                               :name         (s/eq "All Users")
-                              :member_count su/IntGreaterThanZeroPlumatic}
+                              :member_count su/IntGreaterThanZero}
                              (get id->group (:id (perms-group/all-users))))))
               (testing "Administrators Group should be returned"
                 (is (schema= {:id           (s/eq (:id (perms-group/admin)))
                               :name         (s/eq "Administrators")
-                              :member_count su/IntGreaterThanZeroPlumatic}
+                              :member_count su/IntGreaterThanZero}
                              (get id->group (:id (perms-group/admin)))))))]
       (let [id->group (m/index-by :id (fetch-groups))]
         (check-default-groups-returned id->group))
@@ -52,8 +52,8 @@
           (let [id->group (m/index-by :id (fetch-groups))]
             (check-default-groups-returned id->group)
             (testing "empty group should be returned"
-              (is (schema= {:id           su/IntGreaterThanZeroPlumatic
-                            :name         su/NonBlankStringPlumatic
+              (is (schema= {:id           su/IntGreaterThanZero
+                            :name         su/NonBlankString
                             :member_count (s/eq 0)}
                            (get id->group (:id group)))))))))
     (testing "requires superuser"
@@ -80,19 +80,19 @@
                     :last_name     (s/eq "Corv")
                     :email         (s/eq "crowberto@metabase.com")
                     :user_id       (s/eq (mt/user->id :crowberto))
-                    :membership_id su/IntGreaterThanZeroPlumatic}
+                    :membership_id su/IntGreaterThanZero}
                    (get id->member (mt/user->id :crowberto))))
       (is (schema= {:first_name    (s/eq "Lucky")
                     :last_name     (s/eq "Pigeon")
                     :email         (s/eq "lucky@metabase.com")
                     :user_id       (s/eq (mt/user->id :lucky))
-                    :membership_id su/IntGreaterThanZeroPlumatic}
+                    :membership_id su/IntGreaterThanZero}
                    (get id->member (mt/user->id :lucky))))
       (is (schema= {:first_name    (s/eq "Rasta")
                     :last_name     (s/eq "Toucan")
                     :email         (s/eq "rasta@metabase.com")
                     :user_id       (s/eq (mt/user->id :rasta))
-                    :membership_id su/IntGreaterThanZeroPlumatic}
+                    :membership_id su/IntGreaterThanZero}
                    (get id->member (mt/user->id :rasta))))
       (testing "Should *not* include inactive users"
         (is (= nil
@@ -251,10 +251,10 @@
 
     (testing "Return a graph of membership"
       (let [result (mt/user-http-request :crowberto :get 200 "permissions/membership")]
-        (is (schema= {su/IntGreaterThanZeroPlumatic
-                      [{:membership_id su/IntGreaterThanZeroPlumatic
-                        :group_id su/IntGreaterThanZeroPlumatic
-                        :user_id su/IntGreaterThanZeroPlumatic
+        (is (schema= {su/IntGreaterThanZero
+                      [{:membership_id su/IntGreaterThanZero
+                        :group_id su/IntGreaterThanZero
+                        :user_id su/IntGreaterThanZero
                         :is_group_manager s/Bool}]}
                      result))
         (is (= (db/select-field :id 'User) (set (keys result))))))))
diff --git a/test/metabase/api/session_test.clj b/test/metabase/api/session_test.clj
index 02fb0a9f0b86c8d7ef60830582246152ce56992d..dd222888c0f345dfae35262ed3613d8668422fe5 100644
--- a/test/metabase/api/session_test.clj
+++ b/test/metabase/api/session_test.clj
@@ -55,12 +55,12 @@
         (is (schema= SessionResponse
                      response))
         (testing "Login should record a LoginHistory item"
-          (is (schema= {:id                 su/IntGreaterThanZeroPlumatic
+          (is (schema= {:id                 su/IntGreaterThanZero
                         :timestamp          java.time.OffsetDateTime
                         :user_id            (s/eq (mt/user->id :rasta))
                         :device_id          client/UUIDString
-                        :device_description su/NonBlankStringPlumatic
-                        :ip_address         su/NonBlankStringPlumatic
+                        :device_description su/NonBlankString
+                        :ip_address         su/NonBlankString
                         :active             (s/eq true)
                         s/Keyword s/Any}
                        (db/select-one LoginHistory :user_id (mt/user->id :rasta), :session_id (:id response)))))))
@@ -210,8 +210,8 @@
                         :timestamp          java.time.OffsetDateTime
                         :user_id            (s/eq (mt/user->id :rasta))
                         :device_id          client/UUIDString
-                        :device_description su/NonBlankStringPlumatic
-                        :ip_address         su/NonBlankStringPlumatic
+                        :device_description su/NonBlankString
+                        :ip_address         su/NonBlankString
                         :active             (s/eq false)
                         s/Keyword           s/Any}
                        (db/select-one LoginHistory :id login-history-id))))))))
diff --git a/test/metabase/api/setup_test.clj b/test/metabase/api/setup_test.clj
index c4142742b2ab2333802f6b4e57006f838ff226f3..eeda71a228ea4ed93110f628e327a587b1c0cfb7 100644
--- a/test/metabase/api/setup_test.clj
+++ b/test/metabase/api/setup_test.clj
@@ -190,7 +190,7 @@
                                   :details (:details (mt/db))}}
             (testing ":database-create events should have been fired"
               (is (schema= {:topic (schema/eq :database-create)
-                            :item  {:id            su/IntGreaterThanZeroPlumatic
+                            :item  {:id            su/IntGreaterThanZero
                                     :name          (schema/eq db-name)
                                     schema/Keyword schema/Any}}
                            (mt/wait-for-result chan 100))))
diff --git a/test/metabase/driver/common/parameters/values_test.clj b/test/metabase/driver/common/parameters/values_test.clj
index eb8b55196aadd79b7eb4fec4e13b1179aaae2e9a..e273400e16f87ef02e23a3a0c6a4d85fb51ddbc4 100644
--- a/test/metabase/driver/common/parameters/values_test.clj
+++ b/test/metabase/driver/common/parameters/values_test.clj
@@ -529,7 +529,7 @@
                                                   :breakout    [!month.created_at]})}]
         (let [card-tag (str "#" (u/the-id card))]
           (is (schema= {:card-id  (s/eq (u/the-id card))
-                        :query    su/NonBlankStringPlumatic
+                        :query    su/NonBlankString
                         :params   (s/eq ["G%"])
                         s/Keyword s/Any}
                        (#'params.values/parse-tag
diff --git a/test/metabase/driver/sql/parameters/substitute_test.clj b/test/metabase/driver/sql/parameters/substitute_test.clj
index 0b883b3e060d71d7b18d00774402700830184719..3c2039e3c40a400ae62000423c9ff1b473e8d325 100644
--- a/test/metabase/driver/sql/parameters/substitute_test.clj
+++ b/test/metabase/driver/sql/parameters/substitute_test.clj
@@ -519,7 +519,7 @@
 
 ;;; -------------------------------------------- "REAL" END-TO-END-TESTS ---------------------------------------------
 
-(s/defn ^:private checkins-identifier :- su/NonBlankStringPlumatic
+(s/defn ^:private checkins-identifier :- su/NonBlankString
   "Get the identifier used for `checkins` for the current driver by looking at what the driver uses when converting MBQL
   to SQL. Different drivers qualify to different degrees (i.e. `table` vs `schema.table` vs `database.schema.table`)."
   []
diff --git a/test/metabase/driver/sql_jdbc/native_test.clj b/test/metabase/driver/sql_jdbc/native_test.clj
index 6d6e13eb207b929dbce090eca6813233e71b5f55..0f49828f1ec568645f2111b09ccea4d3aabd61c1 100644
--- a/test/metabase/driver/sql_jdbc/native_test.clj
+++ b/test/metabase/driver/sql_jdbc/native_test.clj
@@ -67,7 +67,7 @@
     (is (schema= {:status     (s/eq :failed)
                   :class      (s/eq org.h2.jdbc.JdbcSQLSyntaxErrorException)
                   :error      #"^Column \"ZID\" not found"
-                  :stacktrace [su/NonBlankStringPlumatic]
+                  :stacktrace [su/NonBlankString]
                   :json_query {:native   {:query (s/eq "SELECT ZID FROM CHECKINS LIMIT 2")}
                                :type     (s/eq :native)
                                s/Keyword s/Any}
diff --git a/test/metabase/http_client.clj b/test/metabase/http_client.clj
index ba08bcc41b0a06ea9d632ae227604089e9ccea52..4a402c157e5144791b003da4cd8ca3bb7943c99f 100644
--- a/test/metabase/http_client.clj
+++ b/test/metabase/http_client.clj
@@ -105,12 +105,12 @@
 (declare client)
 
 (def ^:private Credentials
-  {:username su/NonBlankStringPlumatic, :password su/NonBlankStringPlumatic})
+  {:username su/NonBlankString, :password su/NonBlankString})
 
 (def UUIDString
   "Schema for a canonical string representation of a UUID."
   (schema/constrained
-   su/NonBlankStringPlumatic
+   su/NonBlankString
    (partial re-matches #"^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$")))
 
 (schema/defn authenticate :- UUIDString
@@ -179,15 +179,15 @@
 (def ^:private ClientParamsMap
   {(schema/optional-key :credentials)      (schema/maybe (schema/cond-pre UUIDString Credentials))
    :method                                 (apply schema/enum (keys method->request-fn))
-   (schema/optional-key :expected-status)  (schema/maybe su/IntGreaterThanZeroPlumatic)
-   :url                                    su/NonBlankStringPlumatic
+   (schema/optional-key :expected-status)  (schema/maybe su/IntGreaterThanZero)
+   :url                                    su/NonBlankString
    ;; body can be either a map or a vector -- we encode it as JSON. Of course, other things are valid JSON as well, but
    ;; currently none of our endpoints accept them -- add them if needed.
    (schema/optional-key :http-body)        (schema/cond-pre
-                                            (schema/maybe su/MapPlumatic)
+                                            (schema/maybe su/Map)
                                             (schema/maybe clojure.lang.IPersistentVector))
-   (schema/optional-key :query-parameters) (schema/maybe su/MapPlumatic)
-   (schema/optional-key :request-options)  (schema/maybe su/MapPlumatic)})
+   (schema/optional-key :query-parameters) (schema/maybe su/Map)
+   (schema/optional-key :request-options)  (schema/maybe su/Map)})
 
 (schema/defn ^:private -client
   ;; Since the params for this function can get a little complicated make sure we validate them
diff --git a/test/metabase/models/collection/graph_test.clj b/test/metabase/models/collection/graph_test.clj
index dc25ace37c5ee8371ad60c9d9a227868abaeec52..8d9c5d87df9edd0b17323e97f8af9828445ab1f1 100644
--- a/test/metabase/models/collection/graph_test.clj
+++ b/test/metabase/models/collection/graph_test.clj
@@ -339,7 +339,7 @@
                          (nice-graph (graph/graph :currency)))))
 
                 (testing "A CollectionPermissionGraphRevision recording the *changes* to the perms graph should be saved."
-                  (is (schema= {:id         su/IntGreaterThanZeroPlumatic
+                  (is (schema= {:id         su/IntGreaterThanZero
                                 :before     (s/eq (mt/obj->json->obj (assoc before :namespace nil)))
                                 :after      (s/eq {(keyword (str group-id)) {(keyword (str default-ab)) "write"}})
                                 :user_id    (s/eq (mt/user->id :crowberto))
@@ -358,7 +358,7 @@
                          (nice-graph (graph/graph)))))
 
                 (testing "A CollectionPermissionGraphRevision recording the *changes* to the perms graph should be saved."
-                  (is (schema= {:id         su/IntGreaterThanZeroPlumatic
+                  (is (schema= {:id         su/IntGreaterThanZero
                                 :before     (s/eq (mt/obj->json->obj (assoc before :namespace "currency")))
                                 :after      (s/eq {(keyword (str group-id)) {(keyword (str currency-a)) "write"}})
                                 :user_id    (s/eq (mt/user->id :crowberto))
diff --git a/test/metabase/models/collection_test.clj b/test/metabase/models/collection_test.clj
index dbeb58301ac3dd3bd15b262fda6646360427dd9a..3093835c580cdb73b5f118081da7469d8607e428 100644
--- a/test/metabase/models/collection_test.clj
+++ b/test/metabase/models/collection_test.clj
@@ -1252,7 +1252,7 @@
 
   (testing "Does hydrating `:personal_collection_id` force creation of Personal Collections?"
     (mt/with-temp User [temp-user]
-      (is (schema= {:personal_collection_id su/IntGreaterThanZeroPlumatic
+      (is (schema= {:personal_collection_id su/IntGreaterThanZero
                     s/Keyword               s/Any}
                    (hydrate temp-user :personal_collection_id))))))
 
diff --git a/test/metabase/models/login_history_test.clj b/test/metabase/models/login_history_test.clj
index 76da5d044cbf824af3bb40d46b939028022ff8f7..32e8d675c0c6e660585952404b75617509d86047 100644
--- a/test/metabase/models/login_history_test.clj
+++ b/test/metabase/models/login_history_test.clj
@@ -62,7 +62,7 @@
                                                :timestamp #t "2021-04-02T15:52:00-07:00[US/Pacific]"}]]
 
                 (is (schema= {(s/eq email)
-                              [{:from    su/EmailPlumatic
+                              [{:from    su/Email
                                 :to      (s/eq [email])
                                 :subject (s/eq (format "We've Noticed a New Metabase Login, %s" first-name))
                                 :body    [(s/one {:type    (s/eq "text/html; charset=utf-8")
diff --git a/test/metabase/models/permissions_group_test.clj b/test/metabase/models/permissions_group_test.clj
index 254c5033d84d17e3d8c7a267c07f67c67ec62ab4..4474509c9fad34105e681a575d495ec5709cde24 100644
--- a/test/metabase/models/permissions_group_test.clj
+++ b/test/metabase/models/permissions_group_test.clj
@@ -70,7 +70,7 @@
 
 (s/defn ^:private group-has-full-access?
   "Does a group have permissions for `object` and *all* of its children?"
-  [group-id :- su/IntGreaterThanOrEqualToZeroPlumatic object :- perms/Path]
+  [group-id :- su/IntGreaterThanOrEqualToZero object :- perms/Path]
   ;; e.g. WHERE (object || '%') LIKE '/db/1000/'
   (db/exists? Permissions
     :group_id group-id
diff --git a/test/metabase/query_processor/middleware/parameters/native_test.clj b/test/metabase/query_processor/middleware/parameters/native_test.clj
index 06bd645b16fa6a5addbf0eedc50ceefc5e753025..d81062e5550584e2b8d4c5efa279a517ed163808 100644
--- a/test/metabase/query_processor/middleware/parameters/native_test.clj
+++ b/test/metabase/query_processor/middleware/parameters/native_test.clj
@@ -27,7 +27,7 @@
                                          :type         :card
                                          :card-id      (u/the-id card)}}}]
           (binding [driver/*driver* :h2]
-            (is (schema= {:native   su/NonBlankStringPlumatic
+            (is (schema= {:native   su/NonBlankString
                           :params   (s/eq ["G%"])
                           s/Keyword s/Any}
                          (qp.native/expand-inner query)))))))))
diff --git a/test/metabase/query_processor/middleware/parameters_test.clj b/test/metabase/query_processor/middleware/parameters_test.clj
index 3b9cc1fd4c4c14b8857392834e36fa7f54c40c80..3c2b6a48bbde3b4982a30f7d8a3590f2e35d41c5 100644
--- a/test/metabase/query_processor/middleware/parameters_test.clj
+++ b/test/metabase/query_processor/middleware/parameters_test.clj
@@ -303,7 +303,7 @@
                                            :display-name card-tag
                                            :type         :card
                                            :card-id      (u/the-id card)}}})]
-          (is (schema= {:native   {:query    su/NonBlankStringPlumatic
+          (is (schema= {:native   {:query    su/NonBlankString
                                    :params   (s/eq ["G%"])
                                    s/Keyword s/Any}
                         s/Keyword s/Any}
diff --git a/test/metabase/query_processor/test_util.clj b/test/metabase/query_processor/test_util.clj
index 847029ab22d2728c1cf44a348c7f5eeec663e492..fa4dcfbff88e4d42e48d9975a6eddaf8035e28a1 100644
--- a/test/metabase/query_processor/test_util.clj
+++ b/test/metabase/query_processor/test_util.clj
@@ -24,7 +24,7 @@
 ;; TODO - I don't think we different QP test util namespaces? We should roll this namespace into
 ;; `metabase.query-processor-test`
 
-(s/defn ^:private everything-store-table [table-id :- (s/maybe su/IntGreaterThanZeroPlumatic)]
+(s/defn ^:private everything-store-table [table-id :- (s/maybe su/IntGreaterThanZero)]
   (assert (= (:id (qp.store/database)) (data/id))
     "with-everything-store currently does not support switching drivers. Make sure you call with-driver *before* with-everything-store.")
   (or (get-in @@#'qp.store/*store* [:tables table-id])
@@ -32,7 +32,7 @@
         (qp.store/fetch-and-store-tables! [table-id])
         (qp.store/table table-id))))
 
-(s/defn ^:private everything-store-field [field-id :- (s/maybe su/IntGreaterThanZeroPlumatic)]
+(s/defn ^:private everything-store-field [field-id :- (s/maybe su/IntGreaterThanZero)]
   (assert (= (:id (qp.store/database)) (data/id))
     "with-everything-store currently does not support switching drivers. Make sure you call with-driver *before* with-everything-store.")
   (or (get-in @@#'qp.store/*store* [:fields field-id])
diff --git a/test/metabase/query_processor_test/failure_test.clj b/test/metabase/query_processor_test/failure_test.clj
index 54271260d7663edcc6600cc47d064262cfb26637..bceaa03abe6749cbb0ea372c3ecf68b5a08a4f27 100644
--- a/test/metabase/query_processor_test/failure_test.clj
+++ b/test/metabase/query_processor_test/failure_test.clj
@@ -45,7 +45,7 @@
     (is (schema= {:status       (s/eq :failed)
                   :class        Class
                   :error        s/Str
-                  :stacktrace   [su/NonBlankStringPlumatic]
+                  :stacktrace   [su/NonBlankString]
                   ;; `:database` is removed by the catch-exceptions middleware for historical reasons
                   :json_query   (bad-query-schema)
                   :preprocessed (bad-query-preprocessed-schema)
@@ -61,9 +61,9 @@
                   :native       bad-query-native-schema
                   :status       (s/eq :failed)
                   :class        Class
-                  :stacktrace   [su/NonBlankStringPlumatic]
+                  :stacktrace   [su/NonBlankString]
                   :context      (s/eq :question)
-                  :error        su/NonBlankStringPlumatic
+                  :error        su/NonBlankString
                   :row_count    (s/eq 0)
                   :running_time (s/constrained s/Int (complement neg?))
                   :preprocessed (bad-query-preprocessed-schema)
diff --git a/test/metabase/task_test.clj b/test/metabase/task_test.clj
index 09ad7ef35b7865032feb2ceed7da515945e1a646..b23523eb0d046e98faa90fa0bff6430bae676d59 100644
--- a/test/metabase/task_test.clj
+++ b/test/metabase/task_test.clj
@@ -89,12 +89,12 @@
   (testing "Make sure scheduler-info doesn't explode and returns info in the general shape we expect"
     (mt/with-temp-scheduler
       (is (schema= {:scheduler (su/non-empty [s/Str])
-                    :jobs      [{:key         su/NonBlankStringPlumatic
-                                 :description su/NonBlankStringPlumatic
-                                 :triggers    [{:key                 su/NonBlankStringPlumatic
-                                                :description         su/NonBlankStringPlumatic
-                                                :misfire-instruction su/NonBlankStringPlumatic
-                                                :state               su/NonBlankStringPlumatic
+                    :jobs      [{:key         su/NonBlankString
+                                 :description su/NonBlankString
+                                 :triggers    [{:key                 su/NonBlankString
+                                                :description         su/NonBlankString
+                                                :misfire-instruction su/NonBlankString
+                                                :state               su/NonBlankString
                                                 s/Keyword            s/Any}]
                                  s/Keyword    s/Any}]}
                    (task/scheduler-info))))))
diff --git a/test/metabase/test/automagic_dashboards.clj b/test/metabase/test/automagic_dashboards.clj
index 74dc357177a7eb1b719fccac81f283adb1f6b6d1..6482f9873ffecce286c26f384afb7afa9320a9ed 100644
--- a/test/metabase/test/automagic_dashboards.clj
+++ b/test/metabase/test/automagic_dashboards.clj
@@ -28,8 +28,8 @@
   [dashboard]
   (doseq [url (collect-urls dashboard)]
     (testing (format "\nURL = %s" (pr-str url))
-      (is (schema= {:name        su/NonBlankStringPlumatic
-                    :description su/NonBlankStringPlumatic
+      (is (schema= {:name        su/NonBlankString
+                    :description su/NonBlankString
                     s/Keyword    s/Any}
                    (mt/user-http-request :rasta :get 200 (format "automagic-dashboards/%s" (subs url 16))))))))
 
diff --git a/test/metabase/test/data/interface.clj b/test/metabase/test/data/interface.clj
index b8c5dc29d5ef6a902bd1fcaf0ca8981f70a8d5ce..4303750b515842ab072013bf3d7edc395264d615 100644
--- a/test/metabase/test/data/interface.clj
+++ b/test/metabase/test/data/interface.clj
@@ -40,40 +40,40 @@
 (p.types/defrecord+ DatabaseDefinition [database-name table-definitions])
 
 (def ^:private FieldDefinitionSchema
-  {:field-name                         su/NonBlankStringPlumatic
+  {:field-name                         su/NonBlankString
    :base-type                          (s/conditional
                                         #(and (map? %) (contains? % :natives))
-                                        {:natives {s/Keyword su/NonBlankStringPlumatic}}
+                                        {:natives {s/Keyword su/NonBlankString}}
                                         #(and (map? %) (contains? % :native))
-                                        {:native su/NonBlankStringPlumatic}
+                                        {:native su/NonBlankString}
                                         :else
-                                        su/FieldTypePlumatic)
+                                        su/FieldType)
    ;; this was added pretty recently (in the 44 cycle) so it might not be supported everywhere. It should work for
    ;; drivers using `:sql/test-extensions` and [[metabase.test.data.sql/field-definition-sql]] but you might need to add
    ;; support for it elsewhere if you want to use it. It only really matters for testing things that modify test
    ;; datasets e.g. [[metabase.actions.test-util/with-actions-test-data]]
    (s/optional-key :not-null?)         (s/maybe s/Bool)
-   (s/optional-key :semantic-type)     (s/maybe su/FieldSemanticOrRelationTypePlumatic)
-   (s/optional-key :effective-type)    (s/maybe su/FieldTypePlumatic)
-   (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategyPlumatic)
+   (s/optional-key :semantic-type)     (s/maybe su/FieldSemanticOrRelationType)
+   (s/optional-key :effective-type)    (s/maybe su/FieldType)
+   (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategy)
    (s/optional-key :visibility-type)   (s/maybe (apply s/enum field/visibility-types))
-   (s/optional-key :fk)                (s/maybe su/KeywordOrStringPlumatic)
-   (s/optional-key :field-comment)     (s/maybe su/NonBlankStringPlumatic)})
+   (s/optional-key :fk)                (s/maybe su/KeywordOrString)
+   (s/optional-key :field-comment)     (s/maybe su/NonBlankString)})
 
 (def ^:private ValidFieldDefinition
   (s/constrained FieldDefinitionSchema (partial instance? FieldDefinition)))
 
 (def ^:private ValidTableDefinition
   (s/constrained
-   {:table-name                     su/NonBlankStringPlumatic
+   {:table-name                     su/NonBlankString
     :field-definitions              [ValidFieldDefinition]
     :rows                           [[s/Any]]
-    (s/optional-key :table-comment) (s/maybe su/NonBlankStringPlumatic)}
+    (s/optional-key :table-comment) (s/maybe su/NonBlankString)}
    (partial instance? TableDefinition)))
 
 (def ^:private ValidDatabaseDefinition
   (s/constrained
-   {:database-name     su/NonBlankStringPlumatic
+   {:database-name     su/NonBlankString
     :table-definitions [ValidTableDefinition]}
    (partial instance? DatabaseDefinition)))
 
@@ -428,7 +428,7 @@
 
 (def ^:private DatasetTableDefinition
   "Schema for a Table in a test dataset defined by a `defdataset` form or in a dataset defnition EDN file."
-  [(s/one su/NonBlankStringPlumatic "table name")
+  [(s/one su/NonBlankString "table name")
    (s/one [DatasetFieldDefinition] "fields")
    (s/one [[s/Any]] "rows")])
 
@@ -447,7 +447,7 @@
   ([tabledef :- DatasetTableDefinition]
    (apply dataset-table-definition tabledef))
 
-  ([table-name :- su/NonBlankStringPlumatic, field-definition-maps, rows]
+  ([table-name :- su/NonBlankString, field-definition-maps, rows]
    (map->TableDefinition
     {:table-name        table-name
      :rows              rows
@@ -456,7 +456,7 @@
 (s/defn dataset-definition :- ValidDatabaseDefinition
   "Parse a dataset definition (from a `defdatset` form or EDN file) and return a DatabaseDefinition instance for
   comsumption by various test-data-loading methods."
-  [database-name :- su/NonBlankStringPlumatic & table-definitions]
+  [database-name :- su/NonBlankString & table-definitions]
   (s/validate
    DatabaseDefinition
    (map->DatabaseDefinition
@@ -508,7 +508,7 @@
 (s/defn edn-dataset-definition
   "Define a new test dataset using the definition in an EDN file in the `test/metabase/test/data/dataset_definitions/`
   directory. (Filename should be `dataset-name` + `.edn`.)"
-  [dataset-name :- su/NonBlankStringPlumatic]
+  [dataset-name :- su/NonBlankString]
   (let [get-def (delay
                   (let [file-contents (edn/read-string
                                        {:eof nil, :readers {'t #'u.date/parse}}
@@ -536,7 +536,7 @@
 (s/defn transformed-dataset-definition
   "Create a dataset definition that is a transformation of an some other one, seqentially applying `transform-fns` to
   it. The results of `transform-fns` are cached."
-  [new-name :- su/NonBlankStringPlumatic wrapped-definition & transform-fns :- [(s/pred fn?)]]
+  [new-name :- su/NonBlankString wrapped-definition & transform-fns :- [(s/pred fn?)]]
   (let [transform-fn (apply comp (reverse transform-fns))
         get-def      (delay
                       (transform-fn
@@ -585,7 +585,7 @@
 
 (s/defn ^:private tabledef-with-name :- ValidTableDefinition
   "Return `TableDefinition` with `table-name` in `dbdef`."
-  [{:keys [table-definitions]} :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic]
+  [{:keys [table-definitions]} :- DatabaseDefinition, table-name :- su/NonBlankString]
   (some
    (fn [{this-name :table-name, :as tabledef}]
      (when (= table-name this-name)
@@ -594,23 +594,23 @@
 
 (s/defn ^:private fielddefs-for-table-with-name :- [ValidFieldDefinition]
   "Return the `FieldDefinitions` associated with table with `table-name` in `dbdef`."
-  [dbdef :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic]
+  [dbdef :- DatabaseDefinition, table-name :- su/NonBlankString]
   (:field-definitions (tabledef-with-name dbdef table-name)))
 
-(s/defn ^:private tabledef->id->row :- {su/IntGreaterThanZeroPlumatic {su/NonBlankStringPlumatic s/Any}}
+(s/defn ^:private tabledef->id->row :- {su/IntGreaterThanZero {su/NonBlankString s/Any}}
   [{:keys [field-definitions rows]} :- TableDefinition]
   (let [field-names (map :field-name field-definitions)]
     (into {} (for [[i values] (m/indexed rows)]
                [(inc i) (zipmap field-names values)]))))
 
-(s/defn ^:private dbdef->table->id->row :- {su/NonBlankStringPlumatic {su/IntGreaterThanZeroPlumatic {su/NonBlankStringPlumatic s/Any}}}
+(s/defn ^:private dbdef->table->id->row :- {su/NonBlankString {su/IntGreaterThanZero {su/NonBlankString s/Any}}}
   "Return a map of table name -> map of row ID -> map of column key -> value."
   [{:keys [table-definitions]} :- DatabaseDefinition]
   (into {} (for [{:keys [table-name] :as tabledef} table-definitions]
              [table-name (tabledef->id->row tabledef)])))
 
 (s/defn ^:private nest-fielddefs
-  [dbdef :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic]
+  [dbdef :- DatabaseDefinition, table-name :- su/NonBlankString]
   (let [nest-fielddef (fn nest-fielddef [{:keys [fk field-name], :as fielddef}]
                         (if-not fk
                           [fielddef]
@@ -619,7 +619,7 @@
                               (update nested-fielddef :field-name (partial vector field-name fk))))))]
     (mapcat nest-fielddef (fielddefs-for-table-with-name dbdef table-name))))
 
-(s/defn ^:private flatten-rows [dbdef :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic]
+(s/defn ^:private flatten-rows [dbdef :- DatabaseDefinition, table-name :- su/NonBlankString]
   (let [nested-fielddefs (nest-fielddefs dbdef table-name)
         table->id->k->v  (dbdef->table->id->row dbdef)
         resolve-field    (fn resolve-field [table id field-name]
@@ -644,7 +644,7 @@
 (s/defn flattened-dataset-definition
   "Create a flattened version of `dbdef` by following resolving all FKs and flattening all rows into the table with
   `table-name`. For use with timeseries databases like Druid."
-  [dataset-definition, table-name :- su/NonBlankStringPlumatic]
+  [dataset-definition, table-name :- su/NonBlankString]
   (transformed-dataset-definition table-name dataset-definition
     (fn [dbdef]
       (assoc dbdef
diff --git a/test/metabase/util/schema_test.clj b/test/metabase/util/schema_test.clj
index 3c26f997d9335153ba18c79c5a6f98edb4a7d9cf..b28db7225a36ffa5ce866bd5c7cdc0ed74ccd791 100644
--- a/test/metabase/util/schema_test.clj
+++ b/test/metabase/util/schema_test.clj
@@ -8,6 +8,7 @@
    [metabase.api.common :as api]
    [metabase.test :as mt]
    [metabase.util :as u]
+   [metabase.util.malli.schema :as ms]
    [metabase.util.schema :as su]
    [schema.core :as s]))
 
@@ -16,7 +17,7 @@
     (is (= (str "value may be nil, or if non-nil, value must satisfy one of the following requirements: "
                 "1) value must be a boolean. "
                 "2) value must be a valid boolean string ('true' or 'false').")
-           (str (su/api-error-message (s/maybe (s/cond-pre s/Bool su/BooleanStringPlumatic))))))
+           (str (su/api-error-message (s/maybe (s/cond-pre s/Bool su/BooleanString))))))
     (is (= (str/join "\n"
                      ["value must be a map with schema: ("
                       "  a : value must be a map with schema: ("
@@ -40,7 +41,7 @@
   #_{:clj-kondo/ignore [:unused-binding :deprecated-var]}
   [id :as {{dimension-type :type, dimension-name :name} :body}]
   {dimension-type (su/api-param "type" (s/enum "internal" "external"))
-   dimension-name su/NonBlankStringPlumatic})
+   dimension-name su/NonBlankString})
 
 (deftest ^:parallel api-param-test
   (testing "check that API error message respects `api-param` when specified"
@@ -67,10 +68,10 @@
 (deftest translate-exception-message-test
   (mt/with-mock-i18n-bundles {"zz" {:messages {"Integer greater than zero" "INTEGER GREATER THAN ZERO"}}}
     (is (re= #".*Integer greater than zero.*"
-             (ex-info-msg #(s/validate su/IntGreaterThanZeroPlumatic -1))))
+             (ex-info-msg #(s/validate su/IntGreaterThanZero -1))))
     (mt/with-user-locale "zz"
       (is (re= #".*INTEGER GREATER THAN ZERO.*"
-               (ex-info-msg #(s/validate su/IntGreaterThanZeroPlumatic -1)))))))
+               (ex-info-msg #(s/validate su/IntGreaterThanZero -1)))))))
 
 (deftest ^:parallel distinct-test
   (is (= nil
@@ -135,100 +136,100 @@
 
 (deftest malli-and-plumatic-compatibility
   (doseq [{:keys [plumatic malli failed-cases success-cases]}
-          [{:plumatic      su/NonBlankStringPlumatic
-            :malli         su/NonBlankString
+          [{:plumatic      su/NonBlankString
+            :malli         ms/NonBlankString
             :failed-cases  ["" 1]
             :success-cases ["a thing"]}
-           {:plumatic      su/IntGreaterThanOrEqualToZeroPlumatic
-            :malli         su/IntGreaterThanOrEqualToZero
+           {:plumatic      su/IntGreaterThanOrEqualToZero
+            :malli         ms/IntGreaterThanOrEqualToZero
             :failed-cases  ["1" -1 1.5]
             :success-cases [0 1]}
-           {:plumatic      su/IntGreaterThanZeroPlumatic
-            :malli         su/IntGreaterThanZero
+           {:plumatic      su/IntGreaterThanZero
+            :malli         ms/IntGreaterThanZero
             :failed-cases  ["1" 0 1.5]
             :success-cases [1 2]}
-           {:plumatic      su/PositiveNumPlumatic
-            :malli         su/PositiveNum
+           {:plumatic      su/PositiveNum
+            :malli         ms/PositiveNum
             :failed-cases  [0 "1"]
             :success-cases [1.5 2]}
-           {:plumatic      su/KeywordOrStringPlumatic
-            :malli         su/KeywordOrString
+           {:plumatic      su/KeywordOrString
+            :malli         ms/KeywordOrString
             :failed-cases  [1 [1] {:a 1}]
             :success-cases [:a "a"]}
-           {:plumatic      su/FieldTypePlumatic
-            :malli         su/FieldType
+           {:plumatic      su/FieldType
+            :malli         ms/FieldType
             :failed-cases  [:type/invalid :Semantic/*]
             :success-cases [:type/Float]}
-           {:plumatic      su/FieldSemanticTypePlumatic
-            :malli         su/FieldSemanticType
+           {:plumatic      su/FieldSemanticType
+            :malli         ms/FieldSemanticType
             :failed-cases  [:Semantic/invalid :type/Float]
             :success-cases [:type/Category]}
-           {:plumatic      su/FieldRelationTypePlumatic
-            :malli         su/FieldRelationType
+           {:plumatic      su/FieldRelationType
+            :malli         ms/FieldRelationType
             :failed-cases  [:Relation/invalid :type/Category :type/Float]
             :success-cases [:type/FK]}
-           {:plumatic      su/FieldSemanticOrRelationTypePlumatic
-            :malli         su/FieldSemanticOrRelationType
+           {:plumatic      su/FieldSemanticOrRelationType
+            :malli         ms/FieldSemanticOrRelationType
             :failed-cases  [:Relation/invalid :type/Float]
             :success-cases [:type/FK :type/Category]}
-           {:plumatic      su/CoercionStrategyPlumatic
-            :malli         su/CoercionStrategy
+           {:plumatic      su/CoercionStrategy
+            :malli         ms/CoercionStrategy
             :failed-cases  [:type/Category :type/Float]
             :success-cases [:Coercion/ISO8601->Date]}
-           {:plumatic      su/FieldTypeKeywordOrStringPlumatic
-            :malli         su/FieldTypeKeywordOrString
+           {:plumatic      su/FieldTypeKeywordOrString
+            :malli         ms/FieldTypeKeywordOrString
             :failed-cases  [1 :type/FK]
             :success-cases [:type/Float "type/Float"]}
-           {:plumatic      su/FieldSemanticTypeKeywordOrStringPlumatic
-            :malli         su/FieldSemanticTypeKeywordOrString
+           {:plumatic      su/FieldSemanticTypeKeywordOrString
+            :malli         ms/FieldSemanticTypeKeywordOrString
             :failed-cases  [1 :type/FK]
             :success-cases [:type/Category "type/Category"]}
-           {:plumatic      su/FieldPlumatic
-            :malli         su/Field
+           {:plumatic      su/Field
+            :malli         ms/Field
             :failed-cases  [[:aggregation 0] [:field "name" {}]]
             :success-cases [[:field 3 nil] ["field" "name" {:base-type :type/Float}]]}
-           {:plumatic      su/MapPlumatic
-            :malli         su/Map
+           {:plumatic      su/Map
+            :malli         ms/Map
             :failed-cases  [[] 1 "a"]
             :success-cases [{} {:a :b}]}
-           {:plumatic      su/EmailPlumatic
-            :malli         su/Email
+           {:plumatic      su/Email
+            :malli         ms/Email
             :failed-cases  ["abc.com" 1]
             :success-cases ["ngoc@metabase.com"]}
-           {:plumatic      su/ValidPasswordPlumatic
-            :malli         su/ValidPassword
+           {:plumatic      su/ValidPassword
+            :malli         ms/ValidPassword
             :failed-cases  ["abc.com" 1 "PASSW0RD"]
             :success-cases ["unc0mmonpw"]}
-           {:plumatic      su/IntStringPlumatic
-            :malli         su/IntString
+           {:plumatic      su/IntString
+            :malli         ms/IntString
             :failed-cases  [:a "a" "1.5"]
             :success-cases ["1"]}
-           {:plumatic      su/BooleanStringPlumatic
-            :malli         su/BooleanString
+           {:plumatic      su/BooleanString
+            :malli         ms/BooleanString
             :failed-cases  [:false :true true "f"]
             :success-cases ["true" "false"]}
-           {:plumatic      su/TemporalStringPlumatic
-            :malli         su/TemporalString
+           {:plumatic      su/TemporalString
+            :malli         ms/TemporalString
             :failed-cases  ["random string"]
             :success-cases ["2019-10-28T13:14:15" "2019-10-28"]}
-           {:plumatic      su/JSONStringPlumatic
-            :malli         su/JSONString
+           {:plumatic      su/JSONString
+            :malli         ms/JSONString
             :failed-cases  ["string"]
             :success-cases ["{\"a\": 1}"]}
-           {:plumatic      su/EmbeddingParamsPlumatic
-            :malli         su/EmbeddingParams
+           {:plumatic      su/EmbeddingParams
+            :malli         ms/EmbeddingParams
             :failed-cases  [{:key "value"}]
             :success-cases [{:key "disabled"}]}
-           {:plumatic      su/ValidLocalePlumatic
-            :malli         su/ValidLocale
+           {:plumatic      su/ValidLocale
+            :malli         ms/ValidLocale
             :failed-cases  ["locale"]
             :success-cases ["en" "es"]}
-           {:plumatic      su/NanoIdStringPlumatic
-            :malli         su/NanoIdString
+           {:plumatic      su/NanoIdString
+            :malli         ms/NanoIdString
             :failed-cases  ["random"]
             :success-cases ["FReCLx5hSWTBU7kjCWfuu"]}
-           {:plumatic      su/ParameterPlumatic
-            :malli         su/Parameter
+           {:plumatic      su/Parameter
+            :malli         ms/Parameter
             :failed-cases  [{:id   "param-id"
                              :name "param-name"}
                             {:id                   "param-id"
@@ -250,8 +251,8 @@
                              :type                 "number"
                              :values_source_type   "static-list"
                              :values_source_config {:values [[1 2 3]]}}]}
-           {:plumatic      su/ParameterMappingPlumatic
-            :malli         su/ParameterMapping
+           {:plumatic      su/ParameterMapping
+            :malli         ms/ParameterMapping
             :failed-cases  [{:parameter_id "param-id"}
                             {:parameter_id "param-id"
                              :target        [:field 3 nil]