Review: Caddy reverse-proxy block for mail.landscaping-assistant.app
Verdict: NEEDS_REFINEMENT
Template Completeness
- [x] Type: Feature
- [x] Lineage
- [x] Repo
- [x] User Story
- [x] Context
- [x] File Targets
- [x] Feature Flag (none)
- [x] Acceptance Criteria
- [x] Test Expectations
- [x] Constraints
- [x] Checklist
- [x] Related
All required sections present.
Traceability
- [x] story:self-hosted label — "As platform admin, I want zero third-party email dependencies so I control deliverability and avoid Gmail app password rotation"
- [x] story note verified — found in project-stalwart-email user-stories section (key: self-hosted, role: Platform Admin)
- [x] arch:edge-vps label — Hetzner Edge VPS component
- [x] arch note verified — arch-edge-vps note exists in pal-e-docs (Architecture: Hetzner Edge VPS)
- [x] Forgejo issue — ldraney/pal-e-platform#499, state: open
File Targets
- [x]
salt/pillar/caddy.sls— verified: file exists, contains caddy:sites pillar structure with domain/proxy_target/www_redirect keys - [ ]
salt/states/caddy/Caddyfile.j2— MISSING FROM TICKET: template hardcodes:443andtls_server_namefor ALL upstreams. Addingproxy_target: localhost:8080to the pillar would render asreverse_proxy localhost:8080:443withtls_server_name localhost:8080, which is broken. Template needs a conditional for local targets.
Repo Placement
Correct. Issue filed on ldraney/pal-e-platform, which contains both salt/pillar/caddy.sls and salt/states/caddy/Caddyfile.j2. Single-repo fix.
Dependencies
- Blocking: Issue #498 ("Salt: Install Stalwart binary + systemd service on edge VPS") — board item #1733, currently in backlog, state: open. Stalwart must be installed before the reverse proxy can route to it.
- Dependency is documented in the issue Lineage section.
Acceptance Criteria
3 AC + 1 test expectation = 4 total. All are verifiable by an agent post-implementation:
- "https://mail.landscaping-assistant.app loads Stalwart web admin" — curl + status code
- "TLS auto-provisioned by Caddy" — cert issuer check
- "Admin protected by Stalwart's built-in auth" — verify unauthenticated access returns 401/redirect
- curl -I returns 200/302 — straightforward
Missing AC: No regression criterion for existing sites after template change.
Blast Radius
HIGH concern: The Caddyfile.j2 template renders ALL sites. Introducing a conditional for local vs Tailscale targets must preserve backward compatibility for existing sites (palinks.app, landscaping-assistant.app, westsidekingsandqueens.com). A template error would break ALL public-facing services.
Decomposition Assessment
- 2 file targets in 1 repo — acceptable
- 4 acceptance criteria — under threshold
- Estimated agent work: under 5 minutes (pillar entry + template conditional)
- No decomposition needed
Recommendation
[BODY]Add missing file target:salt/states/caddy/Caddyfile.j2— needs conditional to skip:443suffix andtls_server_nametransport for local targets[BODY]Specify pillar schema extension: addlocal: trueflag to the mail site entry in caddy.sls to differentiate localhost targets from Tailscale targets[BODY]Add acceptance criterion: "Existing sites (palinks.app, landscaping-assistant.app, westsidekingsandqueens.com) continue to function after Caddyfile.j2 template change"