# ============================================================
# Maree-CareFlow - cPanel Application Deployment .htaccess
# Version: 1.3.51 | Date: 2026-07-05
#
# This .htaccess is for the CUSTOMER'S cPanel application
# deployment (the React portal + Python backend). It is NOT
# the marketing website .htaccess.
#
# After the setup wizard completes, index.html is the React
# portal SPA - users land directly on the login screen.
# The marketing website (maree.careflow.au) is separate.
#
# CRITICAL: the API reverse-proxy block below forwards every
# /api/* request to the uvicorn backend on 127.0.0.1:8000.
# Without it, /api/* falls through to the SPA fallback and
# returns index.html (HTTP 200, text/html) for every API call.
# The frontend then cannot read an access token or user role,
# so login appears to "succeed" but no admin access is granted.
# ============================================================

# ── Rewrite rules ────────────────────────────────────────────
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  # Force HTTPS (skip when already proxied as https upstream)
  RewriteCond %{HTTPS} off
  RewriteCond %{HTTP:X-Forwarded-Proto} !=https
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

  # Block ALL direct access to the _careflow/ backend directory.
  # Backend files are served only via the Python app (uvicorn).
  RewriteRule ^_careflow(/.*)?$ - [F,L]

  # Allow setup wizard through without SPA fallback
  RewriteCond %{REQUEST_URI} ^/setup/
  RewriteRule ^ - [L]

  # ╔═══════════════════════════════════════════════════════════╗
  # BEGIN MCF-PROXY
  # These rules are for the uvicorn + mod_proxy deployment ONLY.
  # The Passenger deployment ("Setup Python App") serves the API
  # AND the SPA from the Python app itself, so these rules MUST be
  # removed for it - otherwise the 503 safety-net below would
  # answer every /api request with 503 even though Passenger could
  # serve it. passenger_setup.py strips everything between the
  # BEGIN MCF-PROXY / END MCF-PROXY markers automatically.
  # ╚═══════════════════════════════════════════════════════════╝

  # ── API reverse proxy ──────────────────────────────────────
  # Forward the API, interactive docs, and health probe to the
  # uvicorn backend on 127.0.0.1:8000 (started by the installer
  # / systemd unit careflow-api). Requires mod_proxy +
  # mod_proxy_http, which are enabled by default on cPanel/WHM.
  # These rules MUST appear before the SPA fallback so API calls
  # are never answered with index.html.
  <IfModule mod_proxy.c>
    RewriteRule ^(api/.*)$                    http://127.0.0.1:8000/$1 [P,L]
    RewriteRule ^(health)$                    http://127.0.0.1:8000/$1 [P,L]
    RewriteRule ^(docs|redoc|openapi\.json)$  http://127.0.0.1:8000/$1 [P,L]
  </IfModule>

  # Safety net: if mod_proxy is unavailable the rules above never
  # load, so API calls would otherwise fall through to the SPA
  # below and return index.html. Fail loudly with 503 instead -
  # a clear error is far better than a silent broken login.
  RewriteRule ^(api|health|docs|redoc|openapi\.json)(/|$) - [R=503,L]

  # SPA fallback - any route not matching a real file/directory
  # resolves to index.html (the React portal login page)
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^ index.html [L]
  # END MCF-PROXY
</IfModule>

# ── Security Headers ─────────────────────────────────────────
<IfModule mod_headers.c>
  Header always set X-Frame-Options "SAMEORIGIN"
  Header always set X-Content-Type-Options "nosniff"
  Header always set X-XSS-Protection "1; mode=block"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
</IfModule>

# ── Caching ───────────────────────────────────────────────────
<IfModule mod_expires.c>
  ExpiresActive On
  # Hashed assets: 1 year (Vite adds content hash to filenames)
  ExpiresByType text/css               "access plus 1 year"
  ExpiresByType application/javascript "access plus 1 year"
  ExpiresByType image/png              "access plus 1 year"
  ExpiresByType image/svg+xml          "access plus 1 year"
  ExpiresByType image/webp             "access plus 1 year"
  ExpiresByType font/woff2             "access plus 1 year"
  # index.html must not be cached (SPA entry point, changes on deploy)
  ExpiresByType text/html              "access plus 0 seconds"
</IfModule>

# ── Compression ───────────────────────────────────────────────
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/css
  AddOutputFilterByType DEFLATE application/javascript application/json
  AddOutputFilterByType DEFLATE image/svg+xml font/woff2
</IfModule>

# ── Block directory listing ───────────────────────────────────
Options -Indexes

# ── Block direct access to sensitive file types ───────────────
<FilesMatch "\.(env|log|bak|sql|sh|py|cfg|ini|conf|pem|key|htpasswd)$">
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
  <IfModule !mod_authz_core.c>
    Order Allow,Deny
    Deny from all
  </IfModule>
</FilesMatch>
