The previous chapter ended with a warning:
Hold on to your Sorting Hat.
So we did.
The rebuilt configure system was taken out of its test chamber and placed on a genuinely fresh Debian 13 installation.
That real installation did exactly what a serious fresh-install test is supposed to do: it validated the large design, then exposed the remaining assumptions that unit tests had not yet forced into daylight.
The result was not a retreat from the new configurator.
It was the final integration work required to make the whole journey real:
status from flooding IRC and repaired message argument handling across the IRC callbacks.No Perl modules were replaced with Debian packages.
No database schema was changed.
The fresh installation remained a CPAN-only Mediabot installation.
The first fresh attempt reached the dependency stage successfully.
The database had been created.
The application account had been created.
The complete configuration had been generated and audited.
Then the first missing Perl module appeared:
IO::Async::Loop
The installer failed immediately.
At first glance, this looked like a CPAN or Debian 13 problem.
It was neither.
Before the configure revolution, the root wizard entered the installation directory before launching the CPAN script:
cd install
sudo ./cpan_install.sh
Inside cpan_install.sh, the module helper was called using a relative path:
./install_perl_module.sh
That worked only because the caller had already moved into install/.
MB378 modernised the root workflow and launched the script through its real path from the repository root:
sudo /home/mediabot/mediabot_v3/install/cpan_install.sh
But the old helper lookup still depended on the caller’s directory.
The first modules already present appeared healthy.
The first missing module activated the broken path.
CPAN had not failed.
The installer had simply looked for its camel in the wrong tent.
The installer now resolves its own directory:
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
The helper and both logs are derived from that directory:
INSTALL_HELPER="$SCRIPT_DIR/install_perl_module.sh"
SCRIPT_LOGFILE="$SCRIPT_DIR/cpan_install.log"
CPAN_LOGFILE="$SCRIPT_DIR/cpan_install_details.log"
It also enters its own directory before continuing.
The installer now behaves identically when launched:
from install/
from the repository root
through an absolute path
through sudo
The module installation path remains:
cpan -T -i Module::Name
No apt, dpkg, dnf, yum or system Perl package fallback was added.
The fresh wizard also checks the real CPAN toolchain before touching the database:
perl
cpan
make
gcc
mysql
sudo
mktemp
find
curl or wget
If the build environment is incomplete, the installation now stops before creating half of a system.
The camel knows its tent, its logs and its helper — regardless of where the wizard is standing.
With MB380 applied, the next fresh Debian 13 attempt went much further.
CPAN installed the missing modules correctly:
IO::Async
Net::Async::IRC
Config::Simple
Switch
Memory::Usage
String::IRC
DateTime
Moose
Hailo
JSON::MaybeXS
JSON
...
The root verification passed.
Then the installer moved on to the IRC configuration step as the mediabot user and Perl failed on one of its most basic modules:
Can't locate strict.pm:
Permission denied
The module existed.
The runtime user was not allowed to read it.
The new wizard begins with:
umask 077
That is exactly right for:
mediabot.conf;But the same mask was inherited by the CPAN process launched through sudo.
As a result, parts of the Perl site library under /usr/local could be created as:
directories : 0700
files : 0600
Root could install and verify every module.
The mediabot runtime user could not traverse the directories afterwards.
The Restricted Section had been secured so thoroughly that the student who needed the book was also locked out.
The configuration wizard keeps its protective:
umask 077
The CPAN installer now sets its own installation mask:
umask 022
This gives Perl libraries their expected runtime permissions:
directories : 0755
modules : 0644
The CPAN logs remain private in 0600.
When the installer is launched through sudo, those logs are returned to the invoking user using SUDO_UID and SUDO_GID.
MB381 adds:
install/cpan_install.sh --verify-only
This mode:
strict and warnings;After the root CPAN phase, configure automatically runs this verification as the actual mediabot runtime user.
The fresh-install carriage cannot move on merely because root can read the library.
The user who will run the bot must prove it too.
After the CPAN path and permission fixes, the fresh installation demonstrated that the large MB378 redesign was fundamentally sound.
The wizard successfully:
mediabot.sample.conf;[mysql] atomically;The generated configuration was not merely technically complete.
It was also operationally satisfactory during the real test.
That is the important result: the Room of Requirement design survived contact with an actual empty room.
status sent the entire timetable by owl, all at onceOnce the fresh bot connected, registration and login worked.
m uptime worked.
Then came:
m status
The command sent:
4 bot / memory / server lines
1 Scheduler summary
1 line for every Scheduler task
The fresh installation had twelve scheduled tasks.
The result was:
17 consecutive NOTICE messages
The IRC server responded exactly as an IRC server should:
Excess Flood
The connection was closed.
The status command had attempted to deliver the entire Hogwarts timetable through the owlery in a single second.
MB382 changes the normal status into a maximum of three messages:
1. version, bot uptime and memory
2. operating system and server uptime
3. Scheduler summary
Example:
Mediabot v3.2dev-... | bot up 47s | RAM RSS 109.83MB, VM 117.32MB
Server: Linux ... x86_64 | uptime up 0 days, 00:43
Scheduler: 12 total | 12 running | 0 stopped | details: status full
The separators are plain ASCII, avoiding the mojibake previously visible in the Scheduler summary.
The operator can explicitly request:
m status full
m status scheduler
m status tasks
Even the detailed form remains bounded:
normal status : maximum 3 NOTICE messages
full status : maximum 6 NOTICE messages
Scheduler tasks are packed into compact lines such as:
auth_session_cleanup=run/3600s/t0/last:never
If every task cannot fit, the final line reports:
+N more
There is no longer one botNotice() call per task.
The server closed the connection for Excess Flood.
Mediabot then entered on_message_ERROR and crashed with:
Can't use string ("1") as an ARRAY ref
The callback contained:
@{ $message->args // [] }
The problem is Perl context.
args() was evaluated in scalar context before the dereference.
With the current CPAN Net::Async::IRC, scalar context returned the number of arguments:
"1"
The code then attempted the equivalent of:
@{ "1" }
The flood had opened the trapdoor, and the error handler fell through it.
A shared helper now handles the contract:
_irc_message_args($message)
It:
args() in list context;The fix was applied across the IRC callbacks, not only to ERROR.
It now covers paths including:
ERROR
KILL
SERVER
NOTICE
MODE
WHO and WHOIS
LIST
TOPIC
MYINFO
ISUPPORT
INVITE
ERR_NICKNAMEINUSE
ERR_NEEDMOREPARAMS
If an IRC ERROR message contains no usable text, the callback falls back to:
IRC connection closed
The emergency staircase now works even when the main corridor is on fire.
The corrected installation chain and runtime fixes were tested through their focused and historical regressions.
MB378–MB381 installation/configuration chain : 79/79
MB361–MB381 recent regression : 511/511
Status and Scheduler historical regression : 93/93
MB361–MB382 recent regression : 543/543
MB382 was also validated through two installer applications and an idempotent re-execution.
The key source files compile successfully:
configure
install/cpan_install.sh
Mediabot/AdminCommands.pm
mediabot.pl
The regression groups overlap and should not be added into an artificial total.
None.
0 new tables
0 altered columns
0 migrations
0 schema changes
The fresh installation created the normal Mediabot schema.
These rounds did not modify that schema.
Together, these three rounds ensure that:
install/;The real fresh installation did not prove that every first draft was perfect.
It proved something more useful.
It proved that the new configuration architecture was strong enough to be tested honestly, fail visibly, be corrected precisely and continue without abandoning its design.
The first hidden passage was a relative path left behind by an older working directory.
The second was a security mask crossing the boundary between secret files and shared runtime libraries.
The third was a status command that confused “complete” with “send everything immediately”.
And behind that third passage waited an error callback that had never met the current CPAN argument contract.
All four assumptions are now explicit.
The installer knows where it lives.
The library knows who must read it.
The status command knows how many owls it may release.
And the error handler knows that one argument is not an array reference merely because it looks lonely.
The Sorting Hat stayed on.
The bot connected.
And the castle learned a little more about surviving the real world.
— Teuk
You must be logged in to reply.