# GLMChat V2.2 — LiteSpeed / Apache shared-hosting rules
# Direct-deploy package: place these files in the application public web root.

Options -Indexes -MultiViews
DirectoryIndex index.html index.php
ErrorDocument 403 "Forbidden"

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Permit only a concrete ACME HTTP-01 token before HTTPS enforcement.
    # The token grammar deliberately excludes slashes, dots and traversal.
    RewriteRule ^\.well-known/acme-challenge/[A-Za-z0-9_-]{1,200}$ - [L]

    # Reject every other .well-known path. This prevents the React history
    # fallback from returning HTTP 200 for malformed or unrelated requests.
    RewriteRule ^\.well-known(?:/|$) - [F,L,NC]

    # Reject insecure requests without constructing a redirect from Host or any
    # forwarded request header. GLMCHAT_PROXY_TLS may only be set by trusted
    # hosting/proxy configuration and cannot be supplied as an HTTP header.
    RewriteCond %{HTTPS} !=on
    RewriteCond %{ENV:GLMCHAT_PROXY_TLS} !=1
    RewriteRule ^ - [F,L]

    # Block private application directories.
    RewriteRule ^(?:storage|server|tests|scripts|source|verification|handover|evidence|implementation-prompts)(?:/|$) - [F,L,NC]

    # Block hidden files, except ACME validation under .well-known.
    RewriteRule (^|/)\.(?!well-known(?:/|$)) - [F,L]

    # Block sensitive files and build metadata.
    RewriteRule ^(?:build-manifest\.json|DEPLOYMENT_MANIFEST\.json|sbom\.cdx\.json|package(?:-lock)?\.json|VERSION)$ - [F,L,NC]
    RewriteRule \.(?:db|sqlite|sqlite3|log|lock|key|sql|env|ini|bak|md|txt)$ - [F,L,NC]

    # Only the public front controller may execute as PHP.
    RewriteRule ^(?!index\.php$).*\.php$ - [F,L,NC]

    # Route API requests to the PHP front controller.
    RewriteRule ^api(?:/.*)?$ index.php [QSA,L]

    # Serve real public files and directories unchanged.
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # React/PWA history fallback.
    RewriteRule ^ index.html [L]
</IfModule>

<IfModule mod_headers.c>
    Header always unset X-Powered-By
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "DENY"
    Header always set Referrer-Policy "no-referrer"
    Header always set Permissions-Policy "camera=(), geolocation=(), payment=(), usb=()"
    Header always set Strict-Transport-Security "max-age=31536000"
    Header always set Cross-Origin-Opener-Policy "same-origin"
    Header always set Cross-Origin-Resource-Policy "same-origin"
    Header always set Content-Security-Policy "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: blob:; media-src 'self' blob:; object-src 'none'; script-src 'self'; style-src 'self'; style-src-elem 'self'; style-src-attr 'none'; worker-src 'self' blob:"

    # Never cache API/front-controller responses or the PWA shell metadata.
    <FilesMatch "^(?:index\.php|index\.html|manifest\.webmanifest|precache-manifest\.json|sw\.js|registerSW\.js|offline\.html|native-android\.js|offline-runtime\.js|platform-enhancements\.js|icon-192\.png|icon-512\.png|maskable-512\.png|apple-touch-icon-180\.png|favicon-48\.png)$">
        Header always set Cache-Control "no-cache, no-store, must-revalidate"
        Header always set X-LiteSpeed-Cache-Control "no-cache, no-store"
        Header always set Pragma "no-cache"
        Header always set Expires "0"
    </FilesMatch>

    # Long-lived browser caching for fingerprinted production assets.
    <FilesMatch "^(?:index|react|react-dom|workbox-window\.prod\.es5)-[A-Za-z0-9_-]+\.(?:css|js|woff2)$">
        Header always set Cache-Control "public, max-age=31536000, immutable"
    </FilesMatch>
</IfModule>

<IfModule mod_mime.c>
    AddType application/manifest+json .webmanifest
    AddType application/javascript .js
    AddType image/svg+xml .svg
    AddType font/woff2 .woff2
</IfModule>

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

<IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/javascript application/javascript application/json application/manifest+json image/svg+xml
</IfModule>

<IfModule mod_setenvif.c>
    SetEnvIf Authorization "(.+)" HTTP_AUTHORIZATION=$1
</IfModule>
