• docs/superpowers/specs/2026-07-21-door-idle-detection-design.md

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Tuesday, July 21, 2026 21:53:27
    https://gitlab.synchro.net/main/sbbs/-/commit/15780517d5df4349c3e29f17
    Added Files:
    docs/superpowers/specs/2026-07-21-door-idle-detection-design.md
    Log Message:
    doors: design spec for graphical-door idle-user detection

    Synchronet's per-program "Maximum Inactivity" cannot detect an idle user in
    any of the termgfx graphical doors. xtrn_sec.cpp does apply the setting for
    the door's duration, but enforcement in input_thread() tests a counter that
    is reset on any successful socket read -- and every termgfx door paces its frame loop with DSR acks, so the terminal answers ~10x/sec with no human involved. The counter never approaches the threshold. The failure is silent
    and points the safe-looking way: the setting reads as configured, and does nothing.

    Observed on node 11 this afternoon: a SyncRetro NES session 236 minutes in,
    TCP healthy and the door rendering at ~10fps, where every inbound segment
    was exactly 6 bytes (ESC[1;1R, the pace-ack) across 1,759 consecutive
    segments -- not one keystroke. The user had walked away and nothing at any layer was positioned to notice.

    The design puts the clock in the door, where real key events can be told
    apart from terminal auto-replies: a shared termgfx/idle.{h,c} state machine
    fed from the door's key dispatch, a sysop-configurable [idle] section with
    an exempt ARS defaulting to EXEMPT H, and warn-then-exit-to-lobby so a silent-but-engaged user watching a cutscene gets a chance to stay. The door exits rather than hanging up, which lets the BBS's own session inactivity timeout take over once pacing stops.

    Also records a parsing hazard the implementation has to close: the JS parse_duration() in game_lobby.js treats a bare number as days while
    xpdev's C parse_duration() treats it as seconds, and both will read the
    same ini key.

    SyncRetro adopts it first; the other five doors are tracked as follow-on
    work so the divergence stays visible.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Tuesday, July 21, 2026 21:53:27
    https://gitlab.synchro.net/main/sbbs/-/commit/fbdff744f0b711125545a224
    Modified Files:
    docs/superpowers/specs/2026-07-21-door-idle-detection-design.md
    Log Message:
    doors: extend the idle-detection spec to all six graphical doors

    Surveying the other five doors turned up a constraint the first draft did
    not account for: only half of them have a JS lobby. syncretro, syncduke and syncdoom build their command lines in JS and so can evaluate an exempt ARS
    at launch; syncscumm, syncconquer and syncmoo1 are static xtrn.ini entries
    with nowhere to run that check. DOOR32.SYS cannot close the gap either --
    it carries no exempt flags, and termgfx's parser does not even extract the security level.

    So the spec now describes two launch shapes. Lobby doors evaluate
    exempt_ars and pass -i<seconds>; the other three take the same [idle] keys
    from their own ini and additionally honor -i on the static command line.
    The resulting exemption asymmetry is recorded as an accepted consequence
    rather than left to be discovered, along with what it would take to close.

    Also captured per door: the activity hook sites, the mouse hook, the exit
    check and the warning renderer. Two doors grew parallel key dispatchers and need multi-site hooks; hooking their deeper common point is rejected
    because synthetic key-up expiry timers also call it, which would forge
    activity for a user who has left. Mouse motion needs the report handler
    rather than the event queue everywhere except syncscumm, the only door that queues a motion event.

    Three doors need more than a hook. syncscumm has no session time limit at
    all -- termio reads the drop file's limit and discards it -- and no
    transient overlay; both get built in termgfx_termio so syncrpg inherits
    them. syncmoo1 has no overlay either. syncduke has no unified exit check. syncconquer is the cheapest and is proposed as the first target: its
    time-limit function is already a warn-only stub whose own comment invites
    this escalation.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net