     (declare-result "UP01"
                     (empty? matches)
                     (if (empty? matches) "The technology does not extend the Explorer UI." message))))
+
+(defn- up03-repo-min-max
+  [source content-index]
+  (let [repo-mins (distinct (map #(second (first (:re-seq %))) (filter #(= :up03-min (:regex-id %)) content-index)))
+        repo-maxs (distinct (map #(second (first (:re-seq %))) (filter #(= :up03-max (:regex-id %)) content-index)))]
+    (declare-result "UP03"
+                    (or (not (empty? repo-mins)) (not (empty? repo-maxs)))
+                    (s/join "\n"
+                      (filter identity
+                              (vector
+                                (if (not-empty repo-mins)                       (str "module.repo.version.min(s): " (s/join "," repo-mins)))
+                                (if (not-empty repo-maxs)                       (str "module.repo.version.max(s): " (s/join "," repo-maxs)))
+                                (if (and (empty? repo-mins) (empty? repo-maxs)) "The technology does not specify module.editions in its module.properties file(s).")))))))
+
+(defn- up04-module-editions
+  [source content-index]
+  (let [matches  (distinct (map #(second (first (:re-seq %))) (filter #(= :up04 (:regex-id %)) content-index)))
+        editions (s/join "," matches)]
+    (declare-result "UP04"
+                    (not (empty? matches))
+                    (if (empty? matches)
+                      "The technology does not specify module.editions in its module.properties file(s)."
+                      (str "module.editions:" editions)))))
 
 (defn validate
   "Runs all source-based validations."

  {
    :module-properties {
        :module-version #"module\.version\s*=(.*)\z"
        :repo-min       #"module\.repo\.version\.min\s*=(.*)\z"
        :repo-max       #"module\.repo\.version\.max\s*=(.*)\z"
        :alf-edition    #"module\.edition\s*=(.*)\z"
        :com03          #"module\.id\s*=(.*)\z"
      }
    :java {
        :stb08-stb09    #"(?:^|\s)synchronized(?:\s|$)"

         (sec03-none-authentication-in-web-scripts   source content-index)
         (sec05-use-of-eval                          source content-index)
         (up01-explorer-ui-extension                 source file-index)
         (up03-repo-min-max                          source content-index)
         (up04-module-editions                       source content-index)
       )
       (stb08-stb09-use-of-synchronized            source content-index)
       (stb19-stb20-web-script-transaction-setting source content-index)
