Files
novaconium/novaconium/config.php
T
code b882c304b1 Replace Basic Auth with multi-user login, roles, groups, and Lib\Access
Admin login & user management (novaconium/ISSUES.md): session-based
login against a SQLite users table replaces the single-user HTTP Basic
Auth stopgap (admin_username/admin_password_hash and /admin/password-hash
are gone; one admin_auth_enabled flag, off by default with zero DB
footprint). New /admin/login, /admin/logout (POST-only, real page), and
/admin/users pages plus bin/create-admin-user.php.

First user created is the admin; everyone after is registered with a
unique normalized email and an optional group. /admin/* and drafts are
admin-only; Lib\Access gates page content from sidecars
(Access::require('group:members')) with login-redirect/404 responses —
public by default, static pages always public by construction. User
management covers disable/enable, delete, promote/demote, group, email,
and password, with last-active-admin lockout guards.

Also: Session::regenerate() against fixation, friendly missing-PDO-driver
errors in Lib\Db, docs at /admin/docs/access-control and updates across
admin-auth/drafts/sidecars/config/libraries and README/AGENTS.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 00:17:54 +00:00

105 lines
5.6 KiB
PHP

<?php
// These are the framework defaults. A project overrides any subset of them
// by creating App/config.php returning an array of just the keys it wants
// to change — novaconium/bootstrap.php shallow-merges it over this file, the
// same App-over-novaconium override pattern used for pages/ and lib/. This
// file itself is not meant to be edited per-project.
return [
// Ordered override roots: App/pages is checked first so a project can
// override any page, sidecar, or layout by placing one at the same
// relative path there; novaconium/pages supplies the framework defaults.
'pages_dirs' => [
__DIR__ . '/../App/pages',
__DIR__ . '/pages',
],
'cache_dir' => __DIR__ . '/../public/cache',
'debug' => true,
// Site name used as the default page title, og:site_name, and the
// footer copyright line in novaconium/pages/_layout/layout.twig.
'site_name' => 'Novaconium Website',
// Matomo analytics. Leave both empty (the default) to disable tracking
// entirely — the layout emits no tracking script at all in that case.
// Set both via App/config.php to enable, e.g.:
// 'matomo_url' => 'https://matomo.example.com/',
// 'matomo_site_id' => '1',
'matomo_url' => '',
'matomo_site_id' => '',
// Gates every /admin/* route (clear-cache, docs, users, and any future
// admin page) behind a session login against the `users` table on
// Lib\Db's default connection — see /admin/docs/admin-auth. The first
// user created is the admin; users after that are 'registered', each
// with an optional group, and see whatever content sidecars grant via
// Lib\Access (see /admin/docs/access-control) — /admin/* itself 404s
// for them. Off by default because it depends on SQLite (same
// reasoning as content_index_enabled below): when false, /admin/* is
// wide open, /admin/login, /admin/logout, and /admin/users 404,
// Access::require() allows everything, and nothing ever touches
// Lib\Db because of this feature. After enabling it via
// App/config.php, create the first user at /admin/users (open access
// until at least one user exists) or with:
// php novaconium/bin/create-admin-user.php <username>
'admin_auth_enabled' => false,
// Lib\Db (see /admin/docs/database) — named, simultaneously-usable
// connections, keyed by name; 'default' is the only one required. A
// sidecar can use more than one at once, e.g. Db::query(...) (default)
// alongside Db::query(..., 'legacy'). Supported drivers: 'sqlite',
// 'mysql'. The default connection's path deliberately lives outside
// both public/ (must never be web-accessible) and novaconium/ (gets
// wholly replaced on a framework update — see
// /admin/docs/getting-started's "Updating the framework" section) — a
// top-level data/ directory, project-owned like App/, is the only safe
// place for it. migrations_dir is optional per connection (omit it to
// never run migrations against that connection, e.g. a read-only
// legacy database) and accepts either one path or an ordered list of
// roots — the default connection lists novaconium/migrations/ (framework
// -shipped schema, e.g. the content index — see /admin/docs/content-index)
// before App/migrations/ (project migrations), so framework migrations
// always apply first. NOTE: unlike every other key here, App/config.php
// merges into db_connections one level deeper than a normal shallow
// override — see the comment on Lib\Db::config() — so adding a second
// connection there doesn't require repeating 'default'.
'db_connections' => [
'default' => [
'driver' => 'sqlite',
'path' => __DIR__ . '/../data/novaconium.sqlite',
'migrations_dir' => [
__DIR__ . '/migrations',
__DIR__ . '/../App/migrations',
],
],
],
// Routes an admin can preview before the public can see them (see
// /admin/docs/drafts) — a list of Route::$dir-format paths, no leading
// slash, e.g. 'blog/upcoming-post'. Not authenticated as admin (per
// AdminAuth::isAuthenticated()) → 404, same as a route that doesn't
// exist at all, so a draft's existence isn't revealed to anyone
// poking at the URL. Authenticated → renders normally, and — critically
// — is never written to the static HTML cache regardless of whether
// the page has a sidecar (see Renderer::render()'s $isDraft param),
// since a world-readable cached copy would otherwise permanently leak
// the draft the first time an admin previewed it.
'draft_routes' => [],
// Content index (see /admin/docs/content-index) — backs /sitemap.xml,
// /search, and blog tag browsing. Off by default: all three depend on
// SQLite (Lib\Db), a real dependency plenty of sites built on this
// framework won't want at all, the same reasoning that keeps Matomo
// and admin auth off by default above. When false, all three routes
// 404 exactly as if they didn't exist, and nothing ever touches
// Lib\Db because of this feature — no data/novaconium.sqlite gets
// created just because the code exists. content_index_auto only
// matters once enabled: true (the default) reindexes lazily,
// on-demand, the first time a stale index is actually needed (never on
// a normal page view); false disables that and leaves indexing
// entirely to `php novaconium/bin/index-content.php`, e.g. from a
// deploy step.
'content_index_enabled' => false,
'content_index_auto' => true,
];