# Quaeriva — root .htaccess
#
# This file only matters when the hosting account cannot point the document
# root at public/ and serves the project root instead (the common cPanel
# "upload into public_html" case). It does two jobs:
#
#   1. Denies direct web access to everything that is not meant to be served.
#   2. Routes every public request into public/index.php so pretty URLs and
#      assets resolve exactly as they do in the public/ document-root layout.
#
# When the document root IS public/, Apache never reads this file and
# public/.htaccess is in charge instead.

Options -Indexes

# ---------------------------------------------------------------------------
# 1. Deny non-public files
# ---------------------------------------------------------------------------

# Dotfiles: .env, .gitignore, the install lock, editor leftovers.
<FilesMatch "^\.">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Deny from all
    </IfModule>
</FilesMatch>

# Source, data and documentation files that must never be downloadable.
<FilesMatch "\.(?:env|sql|md|zip|tar|gz|log|lock|ini|bak|dist|example)$">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Deny from all
    </IfModule>
</FilesMatch>

<Files "VERSION">
    <IfModule mod_authz_core.c>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core.c>
        Order allow,deny
        Deny from all
    </IfModule>
</Files>

# ---------------------------------------------------------------------------
# 2. Front-controller routing
# ---------------------------------------------------------------------------

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Git metadata and workflow files must never be web-readable when a full
    # source checkout is used directly in public_html. Release archives do not
    # contain them, but the open-source repository must also fail closed.
    RewriteRule ^(?:\.git|\.github)(?:/|$) - [F,L]

    # Application directories are never served directly, whatever they contain.
    # Done as a rewrite as well as a Files rule because mod_authz_core cannot
    # match on directories from here.
    RewriteRule ^(?:app|config|database|docs|tests|bin|resources|storage|install/lib\.php)(?:/|$) - [F,L]

    # Static assets live under public/; expose them at their public paths.
    #
    # Every public directory under public/ needs a rule here. Listing only
    # assets/ meant a theme stylesheet fell through to the front controller,
    # which answered with the HTML 404 page -- the browser then refused it for
    # its MIME type and the site rendered unstyled, which reads as "the theme is
    # broken" rather than as a routing fault. uploads/ has the same shape: a
    # logo, favicon or content image would 404 the same way.
    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^assets/(.*)$ public/assets/$1 [L]

    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^themes/(.*)$ public/themes/$1 [L]

    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^uploads/(.*)$ public/uploads/$1 [L]

    # The installer keeps its own entry point.
    RewriteRule ^install(?:/(?:index\.php)?)?$ install/index.php [QSA,L]

    # The project root is itself a directory, so the !-d guard below would skip
    # it: Apache then looks for a DirectoryIndex, finds no index.php here, and
    # Options -Indexes turns that into 403 on the home page. Route it first.
    RewriteRule ^$ public/index.php [QSA,L]

    # admin/ is a real directory in this layout. admin/.htaccess disables
    # mod_dir's DirectorySlash redirect, while this rule sends /admin and
    # /admin/ through the same front controller. A renamed panel still 404s
    # here, from quaeriva_dispatch().
    RewriteRule ^admin(?:/(.*))?$ public/index.php [QSA,L]

    # Everything that is not a real file or directory goes to the front
    # controller. RewriteBase is left unset so the rules also work when the
    # project sits in a subdirectory.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^ public/index.php [QSA,L]
</IfModule>
