Concept memo: externalizing admin secret settings into their own file
2026-07-19 JST
(Concept stage. Not yet implemented. Awaiting maintainer
[Motoi(gikonekos)]'s decision.)


1. Problem awareness
------------------------------------------------------------
This session dealt with a string of incidents around conf.php's
path-related settings (past-log output failures, counter errors,
issues with install.php's new-key backfill process, migrate.php's
automatic path rewriting).

Separately, it came to light -- pointed out by Kaguya and confirmed
with Motoi(gikonekos) -- that ADMINKEY (the keyword for entering
admin-post mode) is stored in plaintext inside conf.php and matched
via a plain string comparison rather than a crypt-based comparison
(see the README.md ToDo).

Out of this came the idea: why not separate admin secret information
(ADMINPOST, ADMINKEY, etc.) out of conf.php entirely and put it in
its own external file? Reasoning:
  * conf.php is subject to install.php's merge process (backup,
    overwrite, new-key backfill, etc.), and inherently carries the
    risk of the kind of "value unintentionally changes/disappears"
    incident seen this session.
  * If admin secret information is removed from the scope of this
    merge process entirely, the same class of incident becomes
    structurally impossible.


2. Points considered
------------------------------------------------------------

[a] File format: PHP file vs. plain text/ini file

  * PHP-file option:
    Something like
      return array('ADMINPOST' => '...', 'ADMINKEY' => '...');
    loaded via require from bbs.php. PHP source is (as long as the
    server is configured correctly) executed by the web server, so
    there is structurally no path by which its raw contents are
    returned directly to the browser.

  * Text/ini option:
    This depends on `deny all` via .htaccess reliably working.
    During this session, we actually encountered environments where
    an .htaccess php_value directive caused a 500 error, or where it
    only worked via .user.ini on shared hosting. In other words, this
    session confirmed that environments where .htaccess doesn't work
    can genuinely exist.

  * Current impression:
    The PHP-file format is structurally more resilient to .htaccess
    misconfiguration and differences between hosting environments
    (.htaccess is positioned as a belt-and-suspenders addition on
    top). This still needs the maintainer's judgment, though.

[b] Keeping it out of install.php's view

  This external file will not be included in the newbbs/ template
  at all (the same thinking as for real data files like data/,
  logs/, etc.). That way it never appears in install.php's $files
  listing (ksphp_install_list_files(), which only scans files that
  actually exist in the template) and is never subject to copying,
  backup, or overwriting. Following the same idea as "never touch
  path settings," making install.php unaware that the file even
  exists is considered the most reliable way to avoid incidents.

[c] File name

  A name that sounds too "meaningful" (e.g. admin.php) might
  conversely make it an easier target. Whether the naming convention
  should blend it in among other files like conf.php, or instead give
  it a distinctive name and manage it reliably via a .gitignore-style
  exclusion list, is undecided.

[d] Scope

  ADMINPOST and ADMINKEY are the two candidates in scope.
  Non-secret admin settings like ADMINNAME and ADMINMAIL are assumed
  to stay in conf.php as before (undecided, needs confirmation).


3. Current status
------------------------------------------------------------
Concept stage. Not yet implemented. Detailed design will proceed
once the maintainer (Motoi(gikonekos)) weighs in on [a]-[d] above.


4. Related
------------------------------------------------------------
This concept grew out of the README.md ToDo entry recording the
security concern around ADMINKEY's plaintext comparison
(2026-07-19).


5. Implemented (added 2026-07-20)
------------------------------------------------------------
Following discussion with Motoi(gikonekos) on [a]-[d] above, it was
implemented as follows.

[a] File format: adopted the PHP-file option (local.php,
    return array() format)
[b] Excluded from install.php: achieved simply by not including
    local.php in the newbbs/ template (no additional exclusion logic
    was needed, as expected)
[c] File name: the secret-data file itself (local.php) keeps a fixed
    name. Obfuscation/renaming is instead limited to the "password
    setup/change tool" (initial name _setup.php -> renamed by the
    operator to a name of their choosing). The default rename
    candidate is the first 12 characters of
    hash('sha256', date('YmdHi').$SETUP_SEED) plus .php
    ($SETUP_SEED is editable inside the tool).
[d] Scope: ADMINPOST and ADMINKEY only. ADMINNAME and ADMINMAIL
    remain in conf.php as before.

Beyond the original scope (fully decoupling the password mechanism
from install.php), the following operational rule was agreed on as
well: "when local.php doesn't exist, anyone can set it up for the
first time; once it exists, logging in with the current password is
required" (option 1, decided by Motoi(gikonekos)). Option 2
(requiring a passphrase known only to the operator) was rejected, as
it would raise the barrier to installation.

Files implemented: newbbs/_setup.php (new), newbbs/bbs.php (replaced
the embedded-setup flow for when ADMINPOST is unset with a guidance
message, added local.php loading logic), newbbs/conf.php (removed
the ADMINPOST/ADMINKEY entries).
