Forum teuk.org

πŸ” MB678-IV-O β€” Give Partyline Privileged Controls Their Own Restricted Section Without Changing the Keys

in Mediabot Β· started by TeuK Β· yesterday

TeuK Β· yesterday

MB678 reaches its final command-extraction round with a deliberately isolated security boundary.

This round moves the two privileged Partyline controls:

_cmd_eval
_cmd_die

out of the historical Mediabot::Partyline parent and into a dedicated module:

Mediabot::Partyline::Privileged

This is intentionally not another addition to the already large Partyline::Commands module. .eval and .die have a different risk profile from ordinary operator commands: one executes Perl code under strict guards and watchdog/reaping logic, while the other can terminate the running process. They deserve an explicit privileged boundary.

The goal remains unchanged throughout MB678:

Move ownership, preserve behaviour.

No command route, privilege rule, confirmation path, event-loop behaviour, or historical method name was changed.


πŸ” What moved

The following physical implementations moved from:

Mediabot/Partyline.pm

to:

Mediabot/Partyline/Privileged.pm

Methods:

_cmd_eval
_cmd_die

The historical API remains available through:

Mediabot::Partyline->_cmd_eval
Mediabot::Partyline->_cmd_die

because the dedicated module exports the methods back into the parent package.


🧱 Why a dedicated Privileged.pm

Putting these methods into Commands.pm would have worked mechanically, but would have weakened the architecture.

_cmd_eval contains security-sensitive and lifecycle-sensitive behaviour around:

permission guards
confirmation
forking
watchdog timing
non-blocking child reaping
output limits
process isolation
error handling

_cmd_die is equally special because it deliberately controls process termination.

The resulting ownership is therefore explicit:

Partyline::Commands
    ordinary Partyline commands

Partyline::Privileged
    privileged process / code-execution controls

That distinction is useful for future review, hardening, and security audits.


πŸ—οΈ Structural result

After IV-O:

Mediabot/Partyline.pm             :  440 lines
Mediabot/Partyline/Privileged.pm  :  388 lines
Mediabot/Partyline/Commands.pm    : 4529 lines
Mediabot/Partyline/Dispatcher.pm  :  407 lines
Mediabot/Partyline/SessionAuth.pm :  676 lines
Mediabot/Partyline/Transport.pm   : 1012 lines

Most importantly, Partyline.pm now contains exactly five physical implementations:

new
get_port
_runtime_status_path
_runtime_status_payload
_write_runtime_status

There is no longer a physical _cmd_* implementation in the parent.

This is the architectural milestone MB678 was aiming for.


πŸ§ͺ Source contracts updated

Because several historical tests intentionally inspect Partyline source ownership, IV-O updated the relevant source contracts rather than pretending the implementation still physically lived in the old file.

Updated contracts include:

105_partyline_eval_enabled_guard.t
120_partyline_eval_watchdog_uses_usleep.t
531_mb309_partyline_eval_nonblocking_reap.t
825_mb645_update_systemd_contract.t

870_mb678_partyline_karma_commands_extraction.t
872_mb678_partyline_reload_commands_extraction.t
873_mb678_partyline_network_stats_commands_extraction.t
874_mb678_partyline_irc_control_commands_extraction.t
875_mb678_partyline_ai_commands_extraction.t
876_mb678_partyline_runtime_diagnostics_commands_extraction.t
877_mb678_partyline_channel_moderation_commands_extraction.t
878_mb678_partyline_antiflood_commands_extraction.t
879_mb678_partyline_remaining_standard_commands_extraction.t

A new dedicated contract was added:

880_mb678_partyline_privileged_controls_extraction.t

πŸ—οΈ Historical surface

Both historical entry points remained callable through Mediabot::Partyline:

OK: _cmd_eval
OK: _cmd_die

Result:

2/2

The dispatcher therefore does not need a new routing model and existing callers remain compatible.


🎯 Focused validation

The IV-O focused group covered the privileged-control contracts plus the recent MB678 extraction boundaries.

Result:

PASSED : 437/437  (5s)

No targeted regression was found.


⚑ Fast validation lane

The reviewed fast lane was then run with the MB679 progress display:

perl t/test_commands.pl --fast --progress

Result:

Selected: 323 of 763 discovered test file(s)

[====================] 100% [323/323 files | 5982 tests]

PASSED : 5982/5982  (65s)

πŸ”Œ Real runtime validation

The development instance was restarted after the extraction.

Result:

mediabot@dev : active

Partyline continued listening on:

0.0.0.0:23456

The real TCP smoke path returned:

Mediabot Partyline
Please enter your nickname.
Enter your password.

Result:

RC_SMOKE=0

The service journal showed no obvious fatal/runtime loading error.


πŸ›‘οΈ Security audit

The security audit remained completely green:

RC_AUDIT=0

Verdict: GO β€” all 11 security invariants hold.

That result matters especially for this round because the code being moved is explicitly privileged.


🏰 Full regression suite

The full suite was run after targeted, fast, runtime, and security validation:

perl t/test_commands.pl --progress

Result:

[====================] 100% [763/763 files | 15109 tests]

PASSED : 15109/15109  (212s)

No follow-up production fix was necessary.


πŸ“¦ Commit

Version : 3.4dev-20260822_042704
Commit  : fd0b4d3
Branch  : master

πŸ” Give Partyline Privileged Controls Their Own Restricted Section Without Changing the Keys

Commit result:

17 files changed
570 insertions
416 deletions

New files:

Mediabot/Partyline/Privileged.pm
t/cases/880_mb678_partyline_privileged_controls_extraction.t

The commit was successfully pushed to GitHub.


🧭 What remains of MB678

IV-O completes the command extraction phase.

The parent now owns only:

construction
configured port access
runtime-status JSON publication
historical facade/import surface
public line-size compatibility constant

A fresh post-commit snapshot confirms that exact state.

The final MB678 task is therefore not another command extraction.

It is a boundary-closure pass:

remove stale dependencies left in the historical parent
move any dependency to its real owner when required
remove obsolete extraction tombstones/comments
add one final architectural boundary contract
validate targeted + fast + runtime + security + full
commit closure

No behaviour should move during that closure.


πŸͺ„ Why this matters

At the beginning of MB678, Partyline.pm was a large multi-responsibility module.

At the end of IV-O, it has become a small facade/core whose responsibilities can be explained in a few lines.

That is a much stronger stopping criterion than chasing an arbitrary file-size target.

The goal was never to make Partyline.pm disappear.

The goal was to make it obvious why every remaining line belongs there.


πŸ” The Restricted Section has its own door now β€” but the old keys still open exactly what they opened before.

You must be logged in to reply.