# ═══════════════════════════════════════════════════════════════════
#  ORYA OS — web root
# ═══════════════════════════════════════════════════════════════════
#
#  Without this file nothing routes: /bot, /health, /scan/{token} and
#  /report/{token} all 404, because Apache looks for directories with
#  those names and does not find them. Only "/" would work.
#
#  Written for Apache on cPanel. Every block is wrapped in <IfModule>
#  so that a host with a module disabled degrades instead of returning
#  500 for every request — a .htaccess referencing a missing module
#  takes the whole site down, and on shared hosting you cannot see the
#  error log to find out why.
# ═══════════════════════════════════════════════════════════════════


# ── Routing ────────────────────────────────────────────────────────
<IfModule mod_rewrite.c>
    RewriteEngine On

    # cPanel serves subdomains from a directory under the account root,
    # so RewriteBase must be "/" — without it, a subdomain whose docroot
    # is public_html/orya.abrinahost.com builds redirect targets that
    # include the directory name.
    RewriteBase /

    # Real files and directories are served as-is: the stylesheet, the
    # script, the font, the icon. This has to come first, or every asset
    # request would be handed to PHP.
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # Everything else is the router's problem.
    RewriteRule ^ index.php [L]
</IfModule>


# ── Do not serve what should not be served ─────────────────────────
#
# The application lives outside the web root, so in the normal case
# none of this is reachable anyway. These rules are for the case where
# that went wrong — a document root pointed somewhere unexpected, or
# someone moving directories later. The file they protect holds the
# database password, so a wrong guess should not be silently fatal.

<FilesMatch "^\.">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Deny from all
    </IfModule>
</FilesMatch>

<FilesMatch "\.(log|sql|sqlite|json|lock|md|yml|yaml|ini)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Deny from all
    </IfModule>
</FilesMatch>

# Directory listings, in case an index file is ever missing.
<IfModule mod_autoindex.c>
    Options -Indexes
</IfModule>


# ── Headers ────────────────────────────────────────────────────────
#
# PHP sets the full set itself in Http\Security, including the CSP.
# These are the ones that also need to cover static files, which never
# reach PHP: an asset cannot carry a header PHP did not send.
<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "DENY"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"

    # The scanner is a tool, not content. Nothing here should be indexed.
    Header always set X-Robots-Tag "noindex, nofollow"
</IfModule>


# ── Caching ────────────────────────────────────────────────────────
#
# Assets are versioned with ?v= from the application, so a long cache
# is safe: a changed file arrives under a new URL. The font is the
# exception — it is requested without a version (so the preload and the
# @font-face request are one resource rather than two) and is therefore
# cached on filename alone, which is correct because a different font
# would be a different file.
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css                  "access plus 1 year"
    ExpiresByType application/javascript    "access plus 1 year"
    ExpiresByType font/woff2                "access plus 1 year"
    ExpiresByType image/svg+xml             "access plus 1 month"

    # HTML is never cached: a report page shows a data age, and a stale
    # one would lie about it.
    ExpiresByType text/html                 "access plus 0 seconds"
</IfModule>

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/css text/plain
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE image/svg+xml
    # woff2 is already compressed; deflating it again wastes CPU and
    # occasionally makes it bigger.
</IfModule>


# ── Charset ────────────────────────────────────────────────────────
# Every byte this application emits is UTF-8. Saying so stops a host
# whose default is latin1 from rendering the entire interface as
# mojibake.
AddDefaultCharset UTF-8
