diff --git a/CHANGELOG.md b/CHANGELOG.md
index 328feecccf5f2d112bfeedf6d2875cef086fb840..9b599258d14ffaaacab150b353a5a9a9cfdc45f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [2.3.1]
+
+### Added
+
+- Municipality geometries for cities (Flensburg, Kiel, Lübeck, and Neumünster) have been incorporated into [sh_bb.csv](./ckanext/odsh/resources/sh_bb.csv).
+
+### Removed
+
+- The flash message for ODaG evaluation has been removed.
+
+### Fixed
+
+- The delete button for packages is now visible again. It was inadvertently missing in a previous update and has been rectified.
+
+- Fixed missing license properties (`od_conformance`, `ods_conformance`) in the [license configuration](./ckanext/odsh/resources/licenses.json).
+
 ## [2.3.0]
 
 ### Added
diff --git a/ckanext/odsh/resources/licenses.json b/ckanext/odsh/resources/licenses.json
index d30b92ffcd3b5d01243c1d3f252ca915c44ae7ef..e27147fbef3a8d8812c71dee54bb6d9026a296b4 100644
--- a/ckanext/odsh/resources/licenses.json
+++ b/ckanext/odsh/resources/licenses.json
@@ -154,8 +154,8 @@
   },
   {
     "id": "http://dcat-ap.de/def/licenses/cc-by-nd",
-    "is_okd_compliant": false,
-    "is_osi_compliant": false,
+    "od_conformance": "not reviewed",
+    "osd_conformance": "not reviewed",
     "status": "active",
     "title": "Creative Commons Namensnennung -- Keine Bearbeitung (CC BY-ND)",
     "url": "http://creativecommons.org/licenses/by-nd/3.0/"
diff --git a/ckanext/odsh/resources/sh_bb.csv b/ckanext/odsh/resources/sh_bb.csv
index 18edb60f24af6645240fb8cbb16da1a9198fcc19..7d31c85bf8a90f3cc721e9252e3d2c2fbda4dc7e 100644
--- a/ckanext/odsh/resources/sh_bb.csv
+++ b/ckanext/odsh/resources/sh_bb.csv
@@ -1218,6 +1218,10 @@ http://dcat-ap.de/def/politicalGeocoding/regionalKey/010605086	Amt Trave-Land	{"
 http://dcat-ap.de/def/politicalGeocoding/regionalKey/010625270	Amt Trittau	{"type":"Feature","properties":{"name":"Amt Trittau"},"geometry":{"type":"Polygon","coordinates":[[[10.2981,53.5543],[10.2981,53.6783],[10.5153,53.6783],[10.5153,53.5543],[10.2981,53.5543]]]}}
 http://dcat-ap.de/def/politicalGeocoding/regionalKey/010545453	Amt Viöl	{"type":"Feature","properties":{"name":"Amt Viöl"},"geometry":{"type":"Polygon","coordinates":[[[9.0925,54.4778],[9.0925,54.6585],[9.3123,54.6585],[9.3123,54.4778],[9.0925,54.4778]]]}}
 http://dcat-ap.de/def/politicalGeocoding/regionalKey/010615179	Amt Wilstermarsch	{"type":"Feature","properties":{"name":"Amt Wilstermarsch"},"geometry":{"type":"Polygon","coordinates":[[[9.1985,53.8085],[9.1985,53.9863],[9.4483,53.9863],[9.4483,53.8085],[9.1985,53.8085]]]}}
+http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01001000	Stadt Flensburg	{"type":"Feature","properties":{"name":"Stadt Flensburg"},"geometry":{"type":"Polygon","coordinates":[[[9.3573,54.7521],[9.3573,54.8236],[9.5065,54.8236],[9.5065,54.7521],[9.3573,54.7521]]]}}
+http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01002000	Stadt Kiel	{"type":"Feature","properties":{"name":"Stadt Kiel"},"geometry":{"type":"Polygon","coordinates":[[[10.0327,54.2508],[10.0327,54.4314],[10.2186,54.4314],[10.2186,54.2508],[10.0327,54.2508]]]}}
+http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01003000	Stadt Lübeck	{"type":"Feature","properties":{"name":"Stadt Lübeck"},"geometry":{"type":"Polygon","coordinates":[[[10.5547,53.7682],[10.5547,53.9937],[10.9671,53.9937],[10.9671,53.7682],[10.5547,53.7682]]]}}
+http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01004000	Stadt Neumünster	{"type":"Feature","properties":{"name":"Stadt Neumünster"},"geometry":{"type":"Polygon","coordinates":[[[9.9256,54.0178],[9.9256,54.1497],[10.0585,54.1497],[10.0585,54.0178],[9.9256,54.0178]]]}}
 http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01051001	Gemeinde Albersdorf	{"type":"Feature","properties":{"name":"Gemeinde Albersdorf"},"geometry":{"type":"Polygon","coordinates":[[[9.2427,54.111],[9.2427,54.1602],[9.3138,54.1602],[9.3138,54.111],[9.2427,54.111]]]}}
 http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01051002	Gemeinde Arkebek	{"type":"Feature","properties":{"name":"Gemeinde Arkebek"},"geometry":{"type":"Polygon","coordinates":[[[9.2287,54.1446],[9.2287,54.177],[9.2838,54.177],[9.2838,54.1446],[9.2287,54.1446]]]}}
 http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01051003	Gemeinde Averlak	{"type":"Feature","properties":{"name":"Gemeinde Averlak"},"geometry":{"type":"Polygon","coordinates":[[[9.1632,53.9189],[9.1632,53.9587],[9.2287,53.9587],[9.2287,53.9189],[9.1632,53.9189]]]}}
@@ -2329,4 +2333,4 @@ http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01062093	Gemeinde Feldh
 http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01062094	Gemeinde Wesenberg	{"type":"Feature","properties":{"name":"Gemeinde Wesenberg"},"geometry":{"type":"Polygon","coordinates":[[[10.5065,53.8095],[10.5065,53.8567],[10.5652,53.8567],[10.5652,53.8095],[10.5065,53.8095]]]}}
 http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01056025	Gemeinde Helgoland	{"type":"Feature","properties":{"name":"Gemeinde Helgoland"},"geometry":{"type":"Polygon","coordinates":[[[7.8685,54.1693],[7.8685,54.1931],[7.9228,54.1931],[7.9228,54.1693],[7.8685,54.1693]]]}}
 http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01059189	Gemeinde Broderby-Goltoft	{"type":"Feature","properties":{"name":"Gemeinde Broderby-Goltoft"},"geometry":{"type":"Polygon","coordinates":[[[9.6709,54.5153],[9.6709,54.5653],[9.7413,54.5653],[9.7413,54.5153],[9.6709,54.5153]]]}}
-http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01059188	Gemeinde Stapel	{"type":"Feature","properties":{"name":"Gemeinde Stapel"},"geometry":{"type":"Polygon","coordinates":[[[9.1715,54.3157,9.3099],[9.1715,54.3157,],[54.386],],[54.386],9.3099],[9.1715,54.3157,9.3099]]]}}
+http://dcat-ap.de/def/politicalGeocoding/municipalityKey/01059188	Gemeinde Stapel	{"type":"Feature","properties":{"name":"Gemeinde Stapel"},"geometry":{"type":"Polygon","coordinates":[[[9.1715,54.3157],[9.1715,54.386],[9.3099,54.386],[9.3099,54.3157],[9.1715,54.3157]]]}}
diff --git a/ckanext/odsh/templates/package/snippets/package_form.html b/ckanext/odsh/templates/package/snippets/package_form.html
index 9120161850af053e5bf38d15b46a270859d1d3c6..37ef706909c1670e40887bd4b6e294ab620fe416 100644
--- a/ckanext/odsh/templates/package/snippets/package_form.html
+++ b/ckanext/odsh/templates/package/snippets/package_form.html
@@ -26,13 +26,11 @@
     <div class="form-actions">
       <div class="row-fluid">
         <div class="span6">
-          {% block delete_button %}
-            {% if h.check_access('package_delete', {'id': data.id}) and not data.state == 'deleted' %}
-            <a class="btn btn-danger pull-left" href="{% url_for 'dataset.delete', id=data.id %}"
-              data-module="confirm-action" data-module-content="{{ _('Are you sure you want to delete this dataset?') }}">
-              {% block delete_button_text %}{{ _('Delete') }}{% endblock %}</a>
-            {% endif %}
-          {% endblock %}
+          {% if h.check_access('package_delete', {'id': data.id}) and not data.state == 'deleted' %}
+          <a class="btn btn-danger pull-left" href="{% url_for 'dataset.delete', id=data.id %}"
+            data-module="confirm-action" data-module-content="{{ _('Are you sure you want to delete this dataset?') }}">
+            {% block delete_button_text %}{{ _('Delete') }}{% endblock %}</a>
+          {% endif %}
           {% block save_button %}
             <button class="btn btn-primary btn-arrow-right" type="submit" name="save">
               {% block save_button_text %}{{
diff --git a/ckanext/odsh/templates/page.html b/ckanext/odsh/templates/page.html
index e761bb02ccf3b0af92ffe2f6aeb986169bfec04e..caa2ed27d46c5b3f7fd3734cc66c56780a6ed38c 100644
--- a/ckanext/odsh/templates/page.html
+++ b/ckanext/odsh/templates/page.html
@@ -20,21 +20,6 @@
 
         {% block flash %}
           {{ super() }}
-
-          {% if not request.referrer or not request.referrer.startswith(h.odsh_public_url()) %}
-            <div class="alert alert-info alert-dismissible fade show" role="alert">
-              <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
-                <span aria-hidden="true"></span>
-              </button>
-              <h4 class="alert-heading">Evaluation des Offene-Daten-Gesetzes (ODaG)</h4>
-              <p>Für die Evaluation des Offene-Daten-Gesetzes (ODaG) lassen wir eine Umfrage zur Nutzung des Open-Data-Portals durchführen. Wir würden uns freuen, wenn möglichst viele Nutzerinnen und Nutzer an der Umfrage teilnehmen würden:</p>
-              <p style="margin-top: 15px;">
-                <a href="https://insight.uni-speyer.de/ODSH/" class="btn">zum Fragebogen</a><br>
-                <small>(extern beim Deutschen Forschungsinstitut für öffentliche Verwaltung Speyer).</small>
-              </p>
-            </div>
-          {% endif %}
-
         {% endblock %}
 
         {% block toolbar %}
diff --git a/ckanext/odsh/validation.py b/ckanext/odsh/validation.py
index 14151edb6910e859fd6f7294376f70af70805f55..c850252966e648148639e25a7c671e7951550370 100644
--- a/ckanext/odsh/validation.py
+++ b/ckanext/odsh/validation.py
@@ -2,7 +2,9 @@
 import logging
 import csv
 import re
-import urllib.request, urllib.error, urllib.parse
+import urllib.request
+import urllib.error
+import urllib.parse
 import json
 import ckan.logic as logic
 
@@ -69,27 +71,28 @@ def validate_extra_groups(data, requireAtLeastOne, errors):
 def validate_extras(key, data, errors, context):
     log.debug("Validating extras")
     extra_errors = {}
-    
+
     isStaNord = ('id',) in data and data[('id',)][:7] == 'StaNord'
-    harvesting = ('ignore_auth' in context) and (context['ignore_auth'] == True)
+    harvesting = ('ignore_auth' in context) and (
+        context['ignore_auth'] == True)
     owner_org = data[('owner_org',)]
-    lenient_with = tk.config.get('ckanext.odsh.lenient_with','')
+    lenient_with = tk.config.get('ckanext.odsh.lenient_with', '')
 
     is_optional_temporal_start = toolkit.asbool(
         tk.config.get('ckanext.odsh.is_optional_temporal_start', False)
-    ) or ( harvesting and (owner_org in lenient_with) )
+    ) or (harvesting and (owner_org in lenient_with))
 
     require_at_least_one_category = toolkit.asbool(
         tk.config.get('ckanext.odsh.require_at_least_one_category', False)
     )
     validate_extra_groups(
-        data=data, 
-        requireAtLeastOne=require_at_least_one_category, 
+        data=data,
+        requireAtLeastOne=require_at_least_one_category,
         errors=extra_errors
     )
-    
+
     is_date_start_before_date_end(data, extra_errors)
-    
+
     validate_extra_date_new(
         key=key,
         field='issued',
@@ -101,7 +104,7 @@ def validate_extras(key, data, errors, context):
         key=key,
         field='temporal_start',
         data=data,
-        optional=is_optional_temporal_start, 
+        optional=is_optional_temporal_start,
         errors=extra_errors
     )
     validate_extra_date_new(
@@ -115,6 +118,7 @@ def validate_extras(key, data, errors, context):
     if len(list(extra_errors.values())):
         raise toolkit.Invalid(extra_errors)
 
+
 def is_date_start_before_date_end(data, extra_errors):
     start_date = _extract_value(data, 'temporal_start')
     end_date = _extract_value(data, 'temporal_end')
@@ -122,6 +126,7 @@ def is_date_start_before_date_end(data, extra_errors):
         if start_date > end_date:
             extra_errors['temporal_start'] = extra_errors['temporal_end'] = 'Please enter a valid period of time.'
 
+
 def _set_value(data, field, value):
     key = None
     for k in list(data.keys()):
@@ -209,7 +214,7 @@ def known_spatial_uri(key, data, errors, context):
                 poly = pkg.extras.get('spatial', None)
         if (not poly) and require_spatial_uri:
             raise toolkit.Invalid(error_message_spatial_uri_empty)
-        #if has_old_uri and require_spatial_uri:
+        # if has_old_uri and require_spatial_uri:
         #    raise toolkit.Invalid(error_message_spatial_uri_empty)
         else:
             if poly:
@@ -219,23 +224,28 @@ def known_spatial_uri(key, data, errors, context):
             return
 
     extension_path = pkg_resources.resource_filename('ckanext.odsh', '')
-    mapping_path = tk.config.get('ckanext.odsh.spatial.mapping', extension_path + '/resources/schleswig-holstein_geojson.csv')
+    mapping_path = tk.config.get('ckanext.odsh.spatial.mapping',
+                                 extension_path + '/resources/schleswig-holstein_geojson.csv')
 
     not_found = True
     spatial_text = str()
     spatial = str()
-    with open(mapping_path, newline='') as mapping_file:
-      cr = csv.reader(mapping_file, delimiter="\t")
-      for row in cr:
-        if row[0] == value:
-            not_found = False
-            spatial_text = row[1]
-            loaded = json.loads(row[2])
-            spatial = json.dumps(loaded['geometry'])
-            break
-      if not_found:
-        raise toolkit.Invalid(
-            'spatial_uri: uri unknown')
+
+    try:
+        with open(mapping_path, newline='') as mapping_file:
+            cr = csv.reader(mapping_file, delimiter="\t")
+            for row in cr:
+                if row and len(row) > 2 and row[0] == value:
+                    not_found = False
+                    spatial_text = row[1]
+                    loaded = json.loads(row[2])
+                    spatial = json.dumps(loaded.get('geometry', {}))
+                    break
+            if not_found:
+                raise toolkit.Invalid('spatial_uri: uri unknown')
+    except (IOError, json.decoder.JSONDecodeError, KeyError) as e:
+        log.error(f"Error processing spatial mapping: {e}")
+        raise toolkit.Invalid("Error processing spatial mapping")
 
     new_index = next_extra_index(data)
 
@@ -261,7 +271,7 @@ def _copy_spatial_uri_temp_to_extras(data):
         data[('extras', next_index, 'value')] = spatial_uri
     else:
         _set_value(data, 'spatial_uri', spatial_uri)
-    
+
 
 def next_extra_index(data):
     current_indexes = [k[1] for k in list(data.keys())
@@ -275,7 +285,8 @@ def validate_relatedPackage(data):
         try:
             get_package_dict(data)
         except logic.NotFound:
-            raise toolkit.Invalid("relatedPackage: package '{}' not found".format(data))
+            raise toolkit.Invalid(
+                "relatedPackage: package '{}' not found".format(data))
 
 
 def validate_formats(data, errors):
@@ -283,7 +294,8 @@ def validate_formats(data, errors):
         raise toolkit.Invalid('Missing format.')
 
     if not any(data.upper() == obj['key'] for obj in odsh_resource_formats()):
-        raise toolkit.Invalid(_('Only formats on the list of the EU Publications Office are allowed.'))
+        raise toolkit.Invalid(
+            _('Only formats on the list of the EU Publications Office are allowed.'))
 
     return data
 
@@ -293,7 +305,8 @@ def tag_name_validator(value, context):
     """
     tagname_match = re.compile(r'^(?=.*[^\n])[^\n]*$', re.UNICODE)
     if not tagname_match.match(value):
-        raise toolkit.Invalid(_('Invalid tag: "%s". Tags cannot contain line breaks.') % (value))
+        raise toolkit.Invalid(
+            _('Invalid tag: "%s". Tags cannot contain line breaks.') % (value))
     return value
 
 
@@ -302,7 +315,7 @@ def get_validators():
         'known_spatial_uri': known_spatial_uri,
         'odsh_validate_extras': validate_extras,
         'validate_licenseAttributionByText': validate_licenseAttributionByText,
-	      'validate_relatedPackage': validate_relatedPackage,
+        'validate_relatedPackage': validate_relatedPackage,
         'odsh_validate_format': validate_formats,
         'tag_name_validator': tag_name_validator,
     }