diff --git a/VorgabenUI/settings-docker.py b/VorgabenUI/settings-docker.py
deleted file mode 100644
index 7aaf28b..0000000
--- a/VorgabenUI/settings-docker.py
+++ /dev/null
@@ -1,141 +0,0 @@
-"""
-Django settings for VorgabenUI project.
-
-Generated by 'django-admin startproject' using Django 5.2.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/5.2/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/5.2/ref/settings/
-"""
-
-import os
-from pathlib import Path
-
-# Build paths inside the project like this: BASE_DIR / 'subdir'.
-BASE_DIR = Path(__file__).resolve().parent.parent
-
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = os.environ.get("SECRET_KEY")
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = bool(os.environ.get("DEBUG", default=0))
-
-ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS","127.0.0.1").split(",")
-
-
-# Application definition
-
-INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'dokumente',
- 'abschnitte',
- 'stichworte',
- 'mptt',
- 'nested_admin',
-]
-
-MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-]
-
-ROOT_URLCONF = 'VorgabenUI.urls'
-
-TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- },
-]
-
-WSGI_APPLICATION = 'VorgabenUI.wsgi.application'
-
-
-# Database
-# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': BASE_DIR / 'data/db.sqlite3',
- }
-}
-
-
-# Password validation
-# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
-
-AUTH_PASSWORD_VALIDATORS = [
- {
- 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
- },
-]
-
-
-# Internationalization
-# https://docs.djangoproject.com/en/5.2/topics/i18n/
-
-LANGUAGE_CODE = 'de-ch'
-
-TIME_ZONE = 'UTC'
-
-USE_I18N = True
-
-USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/5.2/howto/static-files/
-
-STATIC_URL = '/static/'
-STATIC_ROOT="/home/adebaumann/VorgabenUI/staticfiles/"
-STATICFILES_DIRS= (
- os.path.join(BASE_DIR,"static"),
- )
-
-# Media files (User-uploaded content)
-MEDIA_URL = '/media/'
-MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
-
-# Diagram cache settings
-DIAGRAM_CACHE_DIR = 'diagram_cache' # relative to MEDIA_ROOT
-
-# Default primary key field type
-# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
-
-DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
-DATA_UPLOAD_MAX_NUMBER_FIELDS=10250
-NESTED_ADMIN_LAZY_INLINES = True
diff --git a/code-review.md b/code-review.md
new file mode 100644
index 0000000..c944d1a
--- /dev/null
+++ b/code-review.md
@@ -0,0 +1,512 @@
+# Code Review: vgui-cicd Django Project
+
+**Date:** January 20, 2026
+**Reviewer:** AI Code Review
+**Project Path:** /home/adebaumann/development/vgui-cicd
+
+---
+
+## 1. PROJECT STRUCTURE
+
+### Overview
+The project follows Django conventions with a clear app structure:
+- **VorgabenUI** - Main project settings, URLs, WSGI/ASGI
+- **dokumente** - Core document and Vorgabe models (315 lines)
+- **abschnitte** - Text section models and utilities
+- **stichworte** - Keyword/stichwort models
+- **referenzen** - Reference models (MPTT-based)
+- **rollen** - Role models
+- **pages** - General pages and views
+- **diagramm_proxy** - Diagram caching functionality
+
+### Issues Found
+
+**Minor - settings-docker.py**: The `settings-docker.py` file has duplicate `AUTH_PASSWORD_VALIDATORS` definitions (lines 92-105 and 183-199), which is redundant.
+- **File**: `/home/adebaumann/development/vgui-cicd/VorgabenUI/settings-docker.py` (lines 92-105 and 183-199)
+
+---
+
+## 2. SETTINGS REVIEW
+
+### Critical Issues
+
+**1. Fallback SECRET_KEY in production** (`/home/adebaumann/development/vgui-cicd/VorgabenUI/settings.py`, lines 27-47)
+```python
+SECRET_KEY = os.environ.get('VORGABENUI_SECRET')
+if not SECRET_KEY:
+ is_build_env = any([...])
+ debug_mode = ...
+ if debug_mode or is_build_env:
+ SECRET_KEY = 'dev-fallback-key-for-local-debugging-only-not-for-production-use-12345'
+```
+- **Issue**: Even though there's a check for build environments, the hardcoded fallback key creates a significant security risk if the environment variable is not properly set in production
+- **Recommendation**: The fallback should NEVER be enabled, even in development - require the environment variable to be set
+
+**2. DEBUG mode default** (`/home/adebaumann/development/vgui-cicd/VorgabenUI/settings.py`, line 24)
+```python
+DEBUG = os.environ.get('DEBUG', 'True').lower() in ('true', '1', 'yes', 'on')
+```
+- **Issue**: DEBUG defaults to True, which could expose sensitive information if environment variables are misconfigured
+- **Recommendation**: Require explicit setting of DEBUG to False in production
+
+### Major Issues
+
+**3. ALLOWED_HOSTS with wildcard** (`/home/adebaumann/development/vgui-cicd/VorgabenUI/settings.py`, line 50)
+```python
+ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', "10.128.128.144,localhost,127.0.0.1,*").split(",")
+```
+- **Issue**: Default includes `*` which allows any host - dangerous in production
+- **Recommendation**: Default should not include wildcard; require explicit configuration
+
+**4. No rate limiting on authentication** (`/home/adebaumann/development/vgui-cicd/VorgabenUI/settings.py`)
+- **Issue**: No login throttling or rate limiting configured for authentication endpoints
+- **Recommendation**: Add `django-axes` or similar for brute-force protection
+
+**5. SQLite in production** (`/home/adebaumann/development/vgui-cicd/VorgabenUI/settings.py`, lines 109-114)
+```python
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': BASE_DIR / 'data/db.sqlite3',
+ }
+}
+```
+- **Issue**: SQLite is used as default database - not suitable for production with concurrent access
+- **Recommendation**: Configure PostgreSQL or other production-ready database
+
+### Minor Issues
+
+**6. TIME_ZONE mismatch** (`/home/adebaumann/development/vgui-cicd/VorgabenUI/settings.py`, lines 139-145)
+- **Issue**: `LANGUAGE_CODE = 'de-ch'` but `TIME_ZONE = 'UTC'` - timezone should probably be 'Europe/Zurich' for Swiss deployment
+- **File**: `/home/adebaumann/development/vgui-cicd/VorgabenUI/settings.py` (lines 141)
+
+---
+
+## 3. MODELS REVIEW
+
+### Major Issues
+
+**1. Missing `verbose_name` on models** - Several models are missing proper `verbose_name` in their Meta class:
+- `Stichwort` (`/home/adebaumann/development/vgui-cicd/stichworte/models.py`, lines 4-11) - missing verbose_name
+- `Referenz` (`/home/adebaumann/development/vgui-cicd/referenzen/models.py`, lines 6-27) - missing verbose_name
+- `Rolle` (`/home/adebaumann/development/vgui-cicd/rollen/models.py`, lines 5-11) - missing verbose_name
+- `Person` (`/home/adebaumann/development/vgui-cicd/dokumente/models.py`, lines 22-30) - missing verbose_name
+- `Thema` (`/home/adebaumann/development/vgui-cicd/dokumente/models.py`, lines 32-39) - missing verbose_name
+
+**2. BooleanField with `blank=True` but no default** (`/home/adebaumann/development/vgui-cicd/dokumente/models.py`, line 52)
+```python
+aktiv = models.BooleanField(blank=True)
+```
+- **Issue**: BooleanField should have explicit `default=False` for clarity
+- **Recommendation**: Add `default=False`
+
+**3. No database constraints for date validation** (`/home/adebaumann/development/vgui-cicd/dokumente/models.py`, lines 96-97)
+```python
+gueltigkeit_von = models.DateField()
+gueltigkeit_bis = models.DateField(blank=True,null=True)
+```
+- **Issue**: No database-level constraint ensuring `gueltigkeit_bis >= gueltigkeit_von`
+- **Recommendation**: Add constraint validation or override `save()` method
+
+### Minor Issues
+
+**4. Inconsistent naming in foreign key fields** - Some models use plural related names inconsistently:
+- `autoren` and `pruefende` on `Dokument` use plural (correct)
+- Could consider singular `related_name` for consistency where applicable
+
+**5. Missing `related_name` on some ManyToMany fields** (`/home/adebaumann/development/vgui-cicd/dokumente/models.py`, line 289)
+```python
+autoren = models.ManyToManyField(Person) # Missing related_name
+```
+- **Recommendation**: Add `related_name='changelog_entries'` for clarity
+
+---
+
+## 4. VIEWS REVIEW
+
+### Critical Issues
+
+**1. No CSRF protection on comment endpoints** (`/home/adebaumann/development/vgui-cicd/dokumente/views.py`, lines 321-377)
+```python
+@require_POST
+@login_required
+def add_vorgabe_comment(request, vorgabe_id):
+ # No @csrf_exempt but also no CSRF token verification in the view
+```
+- **Issue**: The view uses `@require_POST` but doesn't verify CSRF tokens for the JSON endpoint
+- **Recommendation**: Add `@csrf_exempt` ONLY if intentionally bypassing, or ensure CSRF is handled via the X-CSRFToken header (which is done in the template)
+
+**Note**: Looking at line 368, the template sends `'X-CSRFToken': getCookie('csrftoken')`, so this is actually properly handled. **Not a bug.**
+
+**2. XSS in comment display** (`/home/adebaumann/development/vgui-cicd/dokumente/views.py`, lines 305-306)
+```python
+escaped_text = escape(comment.text).replace('\n', '
')
+```
+- **Issue**: Using `escape()` is good, but line breaks are converted to `
` which could still be exploited
+- **Note**: The `dangerous_patterns` check at lines 339-343 provides some protection
+- **Recommendation**: Consider using a more robust HTML sanitization library
+
+**3. No input validation on comment length** (`/home/adebaumann/development/vgui-cicd/dokumente/views.py`, line 335)
+```python
+if len(text) > 2000: # Reasonable length limit
+```
+- **Issue**: This is actually properly implemented with a 2000 character limit
+- **Status**: OK
+
+### Major Issues
+
+**4. Referenz view lacks error handling** (`/home/adebaumann/development/vgui-cicd/referenzen/views.py`, lines 11-19)
+```python
+def detail(request, refid):
+ referenz_item = Referenz.objects.get(id=refid)
+```
+- **Issue**: `DoesNotExist` exception not caught - will return 500 error instead of 404
+- **Recommendation**: Use `get_object_or_404` for consistency
+
+### Minor Issues
+
+**5. Search view allows complex regex patterns** (`/home/adebaumann/development/vgui-cicd/pages/views.py`, lines 36-70)
+- **Issue**: The validation is good but the `groupby` usage at line 54 could fail if data is not properly sorted
+- **Recommendation**: Add explicit ordering before groupby
+
+**6. No rate limiting on search** (`/home/adebaumann/development/vgui-cicd/pages/views.py`)
+- **Issue**: Search endpoint could be abused for DoS
+- **Recommendation**: Add rate limiting
+
+---
+
+## 5. URL CONFIGURATION
+
+### Minor Issues
+
+**1. No URL namespace for include** (`/home/adebaumann/development/vgui-cicd/VorgabenUI/urls.py`, lines 31-35)
+```python
+path('dokumente/', include("dokumente.urls")),
+path('stichworte/', include("stichworte.urls")),
+```
+- **Issue**: No `app_name` namespace defined in included apps
+- **Recommendation**: Add `app_name = 'dokumente'` to `dokumente/urls.py` for cleaner reversals
+
+**2. Inconsistent trailing slashes** - Most URLs have trailing slashes but not all - ensure consistency
+
+---
+
+## 6. TEMPLATES REVIEW
+
+### Critical Issues
+
+**1. XSS vulnerability in `standard_detail.html`** (`/home/adebaumann/development/vgui-cicd/dokumente/templates/standards/standard_detail.html`, lines 163-164)
+```html
+{% for ref in vorgabe.referenzpfade %}
+{{ ref|safe }}{% if not forloop.last %}, {% endif %}
+```
+- **Issue**: Using `|safe` on reference paths could allow XSS if malicious content is stored
+- **Recommendation**: Use `escape` filter and handle line breaks separately
+
+**2. JavaScript in template without CSP** (`/home/adebaumann/development/vgui-cicd/dokumente/templates/standards/standard_detail.html`, lines 249-424)
+- **Issue**: Inline JavaScript in template
+- **Note**: CSP headers are set in the view (line 316-317), but inline scripts violate strict CSP
+- **Recommendation**: Move JavaScript to external file
+
+### Major Issues
+
+**3. Missing ARIA labels and roles** - Several accessibility issues:
+- Base template (`/home/adebaumann/development/vgui-cicd/pages/templates/base.html`) has navigation but missing `aria-label` on some elements
+- The mobile navigation could use better ARIA attributes
+
+**4. Missing alt attributes on images** (`/home/adebaumann/development/vgui-cicd/pages/templates/base.html`, lines 39-41)
+```html
+
+```
+- **Issue**: alt is present but could be more descriptive
+- **Status**: Acceptable
+
+### Minor Issues
+
+**5. Hardcoded URLs in templates** (`/home/adebaumann/development/vgui-cicd/dokumente/templates/standards/incomplete_vorgaben.html`, line 21)
+```html
+ /dev/null; then
- log_error "kubectl is not installed or not in PATH"
- exit 1
- fi
-}
-
-# Function to check if Python3 is available
-check_python() {
- if ! command -v python3 &> /dev/null; then
- log_error "python3 is not installed or not in PATH"
- exit 1
- fi
-}
-
-# Function to create the secret
-create_secret() {
- local secret_key="$1"
- local encoded_key
-
- # Base64 encode the secret key
- encoded_key=$(echo -n "$secret_key" | base64 -w 0)
-
- log_info "Creating Kubernetes secret '$SECRET_NAME' in namespace '$NAMESPACE'..."
-
- # Create the secret directly with kubectl
- kubectl create secret generic "$SECRET_NAME" \
- --from-literal="$SECRET_KEY_NAME=$secret_key" \
- --namespace="$NAMESPACE" \
- --dry-run=client -o yaml | kubectl apply -f -
-
- if [ $? -eq 0 ]; then
- log_info "Successfully created/updated secret '$SECRET_NAME'"
- else
- log_error "Failed to create/update secret '$SECRET_NAME'"
- exit 1
- fi
-}
-
-# Function to verify the secret
-verify_secret() {
- log_info "Verifying secret deployment..."
-
- if kubectl get secret "$SECRET_NAME" --namespace="$NAMESPACE" &> /dev/null; then
- log_info "Secret '$SECRET_NAME' exists in namespace '$NAMESPACE'"
-
- # Show secret (without revealing the actual key)
- kubectl describe secret "$SECRET_NAME" --namespace="$NAMESPACE"
- return 0
- else
- log_error "Secret '$SECRET_NAME' not found in namespace '$NAMESPACE'"
- return 1
- fi
-}
-
-# Function to show usage
-show_usage() {
- echo "Usage: $0 [OPTIONS]"
- echo ""
- echo "Options:"
- echo " -n, --namespace NAMESPACE Kubernetes namespace (default: vorgabenui)"
- echo " -s, --secret-name NAME Secret name (default: django-secrets)"
- echo " -k, --key-name NAME Secret key name (default: django-secret-key)"
- echo " -h, --help Show this help message"
- echo ""
- echo "Environment variables:"
- echo " NAMESPACE Override default namespace"
- echo ""
- echo "Examples:"
- echo " $0 # Deploy to vorgabenui namespace"
- echo " $0 -n production # Deploy to production namespace"
- echo " NAMESPACE=staging $0 # Deploy to staging namespace"
-}
-
-# Parse command line arguments
-while [[ $# -gt 0 ]]; do
- case $1 in
- -n|--namespace)
- NAMESPACE="$2"
- shift 2
- ;;
- -s|--secret-name)
- SECRET_NAME="$2"
- shift 2
- ;;
- -k|--key-name)
- SECRET_KEY_NAME="$2"
- shift 2
- ;;
- -h|--help)
- show_usage
- exit 0
- ;;
- *)
- log_error "Unknown option: $1"
- show_usage
- exit 1
- ;;
- esac
-done
-
-# Main execution
-main() {
- log_info "Django SECRET_KEY Deployment Script"
- log_info "==================================="
- log_info "Namespace: $NAMESPACE"
- log_info "Secret Name: $SECRET_NAME"
- log_info "Secret Key Name: $SECRET_KEY_NAME"
- echo ""
-
- # Perform checks
- check_kubectl
- check_python
-
- # Generate new secret key
- log_info "Generating new Django SECRET_KEY..."
- SECRET_KEY=$(generate_secret_key)
-
- if [ -z "$SECRET_KEY" ]; then
- log_error "Failed to generate secret key"
- exit 1
- fi
-
- log_info "Generated secret key (first 10 chars): ${SECRET_KEY:0:10}..."
-
- # Create namespace if it doesn't exist
- if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then
- log_warn "Namespace '$NAMESPACE' does not exist, creating..."
- kubectl create namespace "$NAMESPACE"
- fi
-
- # Create the secret
- create_secret "$SECRET_KEY"
-
- # Verify deployment
- verify_secret
-
- echo ""
- log_info "Deployment completed successfully!"
- log_info "To use this secret in your Django deployment, add the following to your pod spec:"
- echo ""
- echo " env:"
- echo " - name: VORGABENUI_SECRET"
- echo " valueFrom:"
- echo " secretKeyRef:"
- echo " name: $SECRET_NAME"
- echo " key: $SECRET_KEY_NAME"
- echo ""
- log_warn "The old secret key in settings.py has been replaced with environment variable lookup."
- log_warn "Make sure your Django deployment uses the environment variable before deploying."
-}
-
-# Run main function
-main
\ No newline at end of file
diff --git a/scripts/deploy_secret.sh b/scripts/deploy_secret.sh
index 4af545f..02b90b1 100755
--- a/scripts/deploy_secret.sh
+++ b/scripts/deploy_secret.sh
@@ -3,7 +3,7 @@
NAMESPACE="vorgabenui"
SECRET_NAME="django-secret"
-SECRET_FILE="argocd/secret.yaml"
+SECRET_FILE="templates/secret.yaml"
# Check if secret file exists
if [ ! -f "$SECRET_FILE" ]; then