# =============================================================================
#  TAIIH AI — Apache configuration (https://ai.taiih.org)
#  THE AFRICA INDIGENOUS INNOVATION HUB
# -----------------------------------------------------------------------------
#  Works on standard cPanel/Apache hosting with mod_rewrite and mod_headers.
#  nginx users: see DEPLOYMENT.md for the equivalent server block.
# =============================================================================

# --- Defaults ----------------------------------------------------------------
DirectoryIndex index.php
Options -Indexes -MultiViews
AddDefaultCharset UTF-8

# --- Error documents (friendly, never a stack trace) -------------------------
ErrorDocument 403 /403.php
ErrorDocument 404 /404.php
ErrorDocument 500 /404.php

# =============================================================================
#  Security headers (defence in depth — the application also sends these from
#  core/Security.php, so they apply even if mod_headers is unavailable)
# =============================================================================
<IfModule mod_headers.c>
    # Dynamic pages get these from core/Security.php (PHP). To avoid duplicate
    # headers, this block applies them ONLY to static assets — files that PHP
    # never handles, and which therefore need them from the web server.
    <FilesMatch "\.(css|js|mjs|png|jpe?g|gif|svg|ico|webp|avif|woff2?|ttf|eot|txt|xml|json|webmanifest|map)$">
        Header always set X-Content-Type-Options "nosniff"
        Header always set X-Frame-Options "SAMEORIGIN"
        Header always set Referrer-Policy "strict-origin-when-cross-origin"
        Header always set Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=()"
        Header always set Cross-Origin-Opener-Policy "same-origin"
    </FilesMatch>

    # These two only remove information, so they are safe to apply globally.
    Header unset X-Powered-By
    Header unset X-Runtime

    # Once HTTPS is confirmed working, enable HSTS here as well as in PHP:
    # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

ServerSignature Off

# =============================================================================
#  Rewrites
# =============================================================================
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

    # --- 1. Force HTTPS (localhost exempt so local testing stays possible) ---
    RewriteCond %{HTTP_HOST} !^localhost(:[0-9]+)?$ [NC]
    RewriteCond %{HTTP_HOST} !^127\.0\.0\.1(:[0-9]+)?$
    RewriteCond %{HTTPS} !=on
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteCond %{HTTP:CF-Visitor} !scheme":"https
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    # --- 2. Block sensitive directories from direct browser access -----------
    RewriteRule ^(config|core|providers|knowledge|storage|partials)(/|$) - [F,L]

    # --- 3. Block dotfiles and common sensitive artefacts --------------------
    RewriteRule (^|/)\.(?!well-known/) - [F,L]
    RewriteRule ^(composer\.(json|lock)|package(-lock)?\.json|\.env.*|\.git.*|README\.md|DEPLOYMENT\.md|CHANGELOG\.md)$ - [F,L]

    # --- 4. Block direct execution/reading of auxiliary file types -----------
    RewriteRule \.(log|md|json|lock|ini|yml|yaml|bak|old|sql|sh|dist|example)$ - [F,L]
    RewriteRule ^knowledge/ - [F,L]

    # --- 5. Optional clean URLs (uncomment to enable) ------------------------
    # RewriteRule ^status/?$        status.php [L]
    # RewriteRule ^api/chat/?$      api/chat.php [L]
    # RewriteRule ^api/models/?$    api/models.php [L]
    # RewriteRule ^api/health/?$    api/health.php [L]
</IfModule>

# =============================================================================
#  Fallback protection for hosts without mod_rewrite
# =============================================================================
<IfModule mod_authz_core.c>
    # Apache 2.4+: config/, core/, providers/, knowledge/, storage/ carry their
    # own .htaccess files with "Require all denied".
</IfModule>

# =============================================================================
#  Never cache PHP-rendered HTML; assets carry a ?v= cache-buster
# =============================================================================
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css            "access plus 7 days"
    ExpiresByType application/javascript "access plus 7 days"
    ExpiresByType image/png           "access plus 30 days"
    ExpiresByType image/jpeg          "access plus 30 days"
    ExpiresByType image/svg+xml       "access plus 30 days"
    ExpiresByType font/woff2          "access plus 30 days"
</IfModule>

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript \
        application/javascript application/json image/svg+xml
</IfModule>

# =============================================================================
#  Request hardening
# =============================================================================
# NOTE: RequestReadTimeout (mod_reqtimeout) is NOT valid inside .htaccess and
# will cause "500 Internal Server Error" if used here. Set it in the virtual
# host instead — see DEPLOYMENT.md → Apache vhost.
#
# LimitRequestBody is permitted in .htaccess on Apache 2.4 (harmless if the
# module is absent — request size is also enforced in PHP by Security::jsonBody).
<IfModule mod_limits.c>
    LimitRequestBody 262144
</IfModule>

# =============================================================================
#  Protect configuration and include files by extension (belt and braces)
# =============================================================================
<FilesMatch "\.(php|phtml|phar)$">
    <IfModule mod_authz_core.c>
        # only the four protected directories are blocked from outside; PHP files
        # in the web root (index.php, status.php, api/) must remain reachable
    </IfModule>
</FilesMatch>

<FilesMatch "^(secrets\.php|\.env|\.gitignore|composer\.(json|lock)|package\.json)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Deny from all
    </IfModule>
</FilesMatch>
