# Caddy config.
#
# - gendsgn.ru — main production site, auto-TLS via Let's Encrypt.
# - www.gendsgn.ru — 301 redirect to apex (canonical URL).
# - :80 — fallback for raw IP access. Closed by same auth gate (pilot phase).
#
# `handle /api/*` (NOT `handle_path`) — we keep the /api prefix because
# the FastAPI router is mounted at /api/v1/*.
#
# Auth gate: basic_auth for pilot phase (2026-05-23).
# Users managed via caddy/users.caddy.snippet (git history = audit trail).
# Public exclusions: /health (liveness probe), /preview/* (static mockups).
#
# IMPORTANT: route { } block is required to preserve directive order.
# Without route { }, Caddy executes directives in hard-coded default order
# (basic_auth runs before handle), making /health and /preview/* exclusions
# ineffective. With route { }, handlers are matched top-to-bottom as written.

{
    servers {
        # ВКЛЮЧАЕТ raw Authorization/Cookie headers в access log
        # (по default Caddy 2.x редактирует их как "REDACTED").
        # Plain password будет в gendsgn.ru.log + auth_audit.log — оба root-only на VPS.
        # См. forwarder.py _extract_attempted_username для использования.
        log_credentials
    }
}

gendsgn.ru {
    encode zstd gzip

    log {
        output file /var/log/caddy/gendsgn.ru.log {
            roll_size 50MiB
            roll_keep 5
            roll_keep_for 720h
        }
        format json
    }

    # Отдельный лог только для auth-событий.
    # Forwarder (ops/glitchtip-auth-forwarder) читает именно этот файл.
    # Retention 7 дней (меньше чем main log) — содержит plain Base64 credentials.
    log auth_audit {
        output file /var/log/caddy/auth_audit.log {
            roll_size 10MiB
            roll_keep 3
            roll_keep_for 168h
        }
        format json
    }

    route {
        # /health и /preview/* — public, без auth, short-circuit.
        handle /health {
            reverse_proxy backend:8000
        }

        # Static HTML mockups для review (audit alternatives).
        # Public access — без auth (по запросу 2026-05-17).
        handle_path /preview/* {
            root * /srv/preview
            file_server browse
        }

        # Auth gate (applies to all routes below within this route block).
        import caddy/users.caddy.snippet

        # Trade-In MVP subproject (tradein-mvp/) — gendesign-tradein docker stack,
        # подключен через gendesign_shared network. Routes ДО универсального handle
        # потому что Caddy матчит handle-блоки сверху вниз.
        handle /trade-in/api/* {
            # `handle_path /trade-in/api/*` стрипал бы целиком /trade-in/api;
            # FastAPI router замаунтен на /api/v1/trade-in/* — нужен strip только
            # префикса basePath /trade-in (Next.js basePath leak).
            uri strip_prefix /trade-in
            reverse_proxy tradein-backend:8000
        }

        # Matcher `path /trade-in /trade-in/*` ловит И /trade-in (без слеша),
        # И /trade-in/ + /trade-in/anything. Без обоих случаев `handle /trade-in/*`
        # пропускал /trade-in без слеша → попадал в общий frontend → пустой ответ.
        @tradein path /trade-in /trade-in/*
        handle @tradein {
            # Next.js basePath=/trade-in — фронт сам ждёт префикса в URL
            reverse_proxy tradein-frontend:3000
        }

        handle /api/* {
            reverse_proxy backend:8000
        }

        handle {
            reverse_proxy frontend:3000
        }
    }
}

www.gendsgn.ru {
    redir https://gendsgn.ru{uri} permanent
}

# Obsidian Self-hosted LiveSync (CouchDB backend).
# Auto-TLS Let's Encrypt. CORS уже включён на стороне CouchDB через bootstrap
# (см. scripts/setup-couchdb.sh). Basic-auth — на стороне CouchDB (admin user).
#
# DNS: A-record obsidian.gendsgn.ru → IP VPS.
# Клиенты Obsidian + Self-hosted LiveSync plugin указывают на этот URL.
obsidian.gendsgn.ru {
    encode zstd gzip

    reverse_proxy couchdb:5984 {
        # Большие документы (vault attachments / images) — увеличиваем timeout
        transport http {
            response_header_timeout 120s
        }
    }
}

# GlitchTip — self-hosted error tracking (Sentry-compatible).
# DNS: A-record errors.gendsgn.ru → IP VPS.
errors.gendsgn.ru {
    encode zstd gzip

    reverse_proxy glitchtip-web:8080

    log {
        output file /var/log/caddy/errors.gendsgn.ru.log
    }
}

# Forgejo — self-hosted git (migration 2026-05-16).
# DNS: A-record git.gendsgn.ru → IP VPS.
# Forgejo container из forgejo-migration/docker-compose.yml на shared
# gendesign_default network. HTTP port 3000 (default Forgejo).
# Был добавлен вручную при migration, потерян при первом auto-deploy после
# изменения Caddyfile (deploy.yml делает git reset --hard). См. fix issue.
git.gendsgn.ru {
    encode zstd gzip

    reverse_proxy forgejo:3000

    log {
        output file /var/log/caddy/git.gendsgn.ru.log
    }
}

# Plain HTTP by IP — closed by same auth gate (prevent bypass via direct IP / SSH tunnel).
# Caddy issues no TLS here (no hostname). /health remains public.
:80 {
    encode zstd gzip

    route {
        # /health — public, без auth (GHA deploy smoke check, liveness probe).
        handle /health {
            reverse_proxy backend:8000
        }

        # Auth gate (same snippet as gendsgn.ru).
        import caddy/users.caddy.snippet

        handle /api/* {
            reverse_proxy backend:8000
        }

        handle {
            reverse_proxy frontend:3000
        }
    }
}
# Test deploy flow 2026-05-15T21:43:32Z
