ANetBBS Changelog
Versions are internal build numbers. Public releases are tagged
separately. Current release: v1.0b2.58 (July 2026). Full release: August 1 2026.
v1.0a2.124 — eventlet Python 3.13 piwheels fix; ANetIRC F2/PgUp/PgDn (June 2026)
Fix eventlet crash on Python 3.13 systems where piwheels ships eventlet 0.37.0
without the start_joinable_thread attribute (the wheel was compiled before the
patch merged). update.sh now greps the installed eventlet/green/thread.py
source file directly and force-rebuilds from source (--no-binary eventlet) if
the fix is absent. The rollback block no longer wipes application files for this
class of failure — it instead auto-fixes eventlet, retries the web service, and
prints a manual fix command if the retry still fails.
Fix ANetIRC F2 key exiting the IRC client instead of toggling the user list:
ui_read_key() only handled \x1b[* (CSI) sequences; F2 on xterm/SSH sends
\x1bOQ (SS3), which fell through to return KEY_ESC → exiting in startup mode.
Added else if (s[0] == 'O') branch: F1=\x1bOP, F2=\x1bOQ, F3=\x1bOR,
F4=\x1bOS. F2 now correctly maps to KEY_F2 → toggles the users panel.
Fix ANetIRC freeze/timing: PTY bridge _input_pump previously read one byte at
a time from the SSH session and wrote one byte at a time to the PTY. The asyncio
scheduler delay between bytes could exceed the C code's 100 ms VTIME, truncating
escape sequences mid-read. Changed to session.read_raw(64) (chunk reads) so
multi-byte sequences (\x1bOQ, \x1b[5~) arrive at the PTY in a single write.
Also replaced deprecated asyncio.get_event_loop() with get_running_loop().
v1.0a2.123 — MRC scrollback stability; arrow-key scroll; escape-seq drain (June 2026)
Fix /scroll scrollback drifting: when scrolled up, _emit now increments
_scroll_offset by the number of new lines added so the historical view stays
locked even as new messages arrive. Up/Down arrow keys now scroll the chat view
1 line (previously swallowed). Fix /scroll up N parsing (strip before isdigit).
Fix PgUp/PgDn escape sequences polluting the input buffer (drain trailing bytes).
Sending a message while scrolled auto-snaps to the live (bottom) view. Added
_scroll_chat(delta) helper; /scroll 0 / /scroll bottom / /scroll live
all return to the live view. Updated docstring.
v1.0a2.122 — MRC input visibility; /scroll; wall color; fast logon fixes (June 2026)
Fix MRC terminal input not showing while typing: _redraw_chat_area was clearing the
input row on every incoming message, erasing the SSH client's local echo. Fixed by not
touching the input row during chat area redraws — only _draw_input_line() (called per
keystroke) updates that row. Added /scroll [n] / /scroll down [n] / /scroll 0
command for scrolling through chat history; status bar shows PAUSED+N when scrolled.
Removed /split on|off command (not needed). Fixed graffiti wall color scheme not
updating after admin change: now reads .env directly at render time instead of using
a stale config class. Fixed fast logon prompt never appearing: same root cause — now
reads .env directly at login time.
v1.0a2.121 — Terminal MRC client rewrite (June 2026)
Complete rewrite of mrc_chat.py. Fixed core scroll bug: word-wrapped messages
were writing past the DECSTBM scroll region into the input row, corrupting it.
Now each wrapped line emits as its own scroll event so the cursor never escapes
the scroll region. Added 60-second WebSocket keepalive ping (latency shown in
status bar). Added IAMHERE AWAY tracking after 10 min idle (matches ANetMRC
behaviour). New commands: /afk, /back, /broadcast, /ctcp, /roomconfig, /status.
Documented ANSI menu override slots in docs/04-ansi-screens.md.
v1.0a2.120 — IRC presets admin; who's online fix; colored sysop/chat menus; screen-clear (June 2026)
Remove MRC-IRC bridge admin; add IRC Server Presets (/admin/irc-presets) with per-preset
name/server/port/SSL/nick/channels. Fix who's online: background heartbeat task every 2 min.
Colored IRC chat menu with Q-to-quit and screen-clear. Chat Systems menu screen-clear fixed.
All sysop terminal sub-menus now colorized and support ANSI overrides (sysop_menu/sysop_users/
sysop_boards/sysop_status.ans slots). New IrcPreset model (irc_presets table, auto-created).
v1.0a2.119 — Security levels, graffiti wall, logon/logoff modules, fast logon (June 2026)
Security levels (0–255) on all content areas (boards, file areas, echomail, RSS).
New graffiti wall feature with pipe colors, pagination, and admin panel.
Logon/logoff module system — run wall/ANSI/shell/door at login or logout.
Fast logon option lets users skip intro modules. Menu action_type = wall added.
v1.0a2.118 — Add: @BPS:NNNN@ throttled ANSI output; add @CLS@ clear-screen (June 2026)
@BPS:NNNN@ in any ANSI screen file now throttles output to simulate the
specified modem baud rate (300–56000). 9600 bps = 960 bytes/sec; output is
sent in 48-byte chunks every 50 ms for smooth rendering. The goodbye, welcome,
newuser, and custom ANSI slots all support it. Also added @CLS@ which
outputs ESC[2J ESC[H (clear screen + cursor home).
v1.0a2.117 — Fix: @-code / display code substitution in ANSI screens (June 2026)
All Synchronet @-codes that resolve user identity (@ALIAS@, @USER@, @NAME@,
@HANDLE@, @REAL@, @FIRST@, @EMAIL@, @LOCATION@, @CALLS@, @SECURITY@)
were returning blank because session.user is a dict but the resolver used
getattr() instead of .get(). Fixed. Also: display_name and location added
to the user dict; @SECURITY@ bool comparison fixed; @VER@/@VERSION@ now
returns the real build version. Parametric codes like @BPS:19200@ are now stripped
instead of printing as literal text.
v1.0a2.116 — Add per-game FOSSIL driver checkbox; fix TW2002 black screen (June 2026)
Replaced FOSSIL driver auto-detection (introduced in v1.0a2.113) with an explicit
per-game checkbox in the Game admin: Requires FOSSIL Driver (BNU.COM / X00.COM).
Check it for games like Zombie Slots / Mega Slots that ship a FOSSIL driver and
need it loaded. Leave it unchecked for TW2002 — dosemu2 virtual COM1 conflicts
with FOSSIL drivers and caused the black screen regression. The needs_fossil_driver
column is auto-migrated by update.sh Step 7.
v1.0a2.115 — Fix: TW2002 black screen; fix game terminal right-side overflow (June 2026)
FOSSIL auto-detection (v1.0a2.113) loaded BNU.COM/FOSSIL.COM if present in the
game dir. TW2002 uses dosemu2 virtual COM1 which conflicts with any FOSSIL driver
— loading one caused a black screen. FOSSIL auto-load now skipped for TW2002.
Game terminal CSS: Bootstrap .container + padding: 24px limited content area
to ~700px on laptop viewports. 80-col terminal needs ~784px → rightmost ~20
columns overflowed outside the green border, showing game sidebars/stat panels
floating beside the terminal box. Fix: max-width: 100% override + overflow:
hidden clip on #terminal-wrap.
v1.0a2.114 — Fix: web door-game terminal animation ghosting (June 2026)
Full-screen animation door games (slot machines, etc.) showed ghost artifacts
in the web game terminal — previous animation frames persisting visually while
new frames drew on top. SSH/telnet sessions were unaffected.
Root cause: xterm.js retains a 1000-line scrollback buffer by default. When a
door game fills the 25-row screen, the terminal scrolls, pushing the current
frame into the scrollback. The game then homes the cursor and redraws, but
the scrollback content remains visible above the viewport, creating doubled
headers/footers. Fix: scrollback: 0 — DOS door games are 80×25 full-screen
apps that reuse the same grid via cursor addressing and need no scrollback.
v1.0a2.113 — Fix: terminal DATABASE_URL; clean release tarball (June 2026)
Terminal service (anetbbs/main.py) hardcoded anetbbs.db instead of
respecting DATABASE_URL from .env, splitting terminal and web onto
different databases. Menu changes, password resets, and door configs made
via the web had no effect in terminal sessions. Fix: resolution order is now
ANETBBS_DB_URL → DATABASE_URL (from .env) → absolute-path fallback.
Release tarball now excludes doors/dos/ (x86 DOS game binaries, sysop-
installed) and data/ftp_root/ (created by installer). Tarball returns to
~29 MB. Pi/ARM installs no longer fail on oversized tarball with wrong-arch
binaries.
dosemu2 door launch now auto-creates the game working directory if missing.
%P in command_line_args now correctly maps to I:\ (per-node scratch
drive) instead of a Linux path in the generated bat file. FOSSIL drivers
(BNU.COM etc.) are auto-loaded if present in the game directory.
v1.0a2.112 — Fix: dosemu2 bat generic for non-TW2002 games; TW2002 ANSI via DORINFO1.DEF (June 2026)
dosemu2 _ANET.BAT was TW2002-only for all door games. _build_dosemu_command() was
injecting SET TWNODE=1, MKDIR I:\NODE2, and COPY I:\DOOR.SYS I:\NODE2\DOOR.SYS into
the generated batch file for every door_dosemu game. These lines are TW2002-specific
(node config environment variable + TW2002's per-node drop-file path). Fixed: the three
lines are now conditional on the game slug containing "tw2002". Any other DOS game
launched via dosemu2 now gets a clean generic bat. Also added DOOR32.SYS and
DORINFO1.DEF copies to the generic path so games using those drop file types find them
in their working directory.
TW2002 ANSI colors require DORINFO1.DEF, not DOOR.SYS. When using DOOR.SYS, TW2002
detects ANSI by sending an ESC[6n cursor-position probe via COM1 and waiting for the
terminal reply. This round-trip through dosemu2's pts COM1 is timing-sensitive and
unreliable — TW2002 times out and falls back to ASCII. DORINFO1.DEF carries an explicit
ANSI flag (line 10 = 1) with no probe needed. Set Drop File Type = DORINFO1.DEF
and Drop File Path = %P in the ANetBBS game admin. In TEDIT.EXE set BBS Drop file
type = RBBS (TW2002's name for the DORINFO1.DEF format), I/O Type = Standard,
Comport = 1. Confirmed working with full ANSI color output.
v1.0a2.111 — Fix: SQLite path on new installs; MRC defaults SSL+5001; security questions for password recovery (June 2026)
Terminal "unable to open database file" on new installs fixed. main.py now always
derives DATABASE_URL from its own __file__ location (same as serve.py has done since
v1.0a2.70), rather than trusting whatever the EnvironmentFile supplies. An .env with a
stale or relative path can no longer cause every telnet/SSH session to fail at DB open time.
Custom Postgres or alternate SQLite paths still use ANETBBS_DB_URL.
MRC bridge default connection changed to SSL port 5001. Fresh install.sh runs now
generate mrc/bridge/config.json with "mrc_port": 5001 and "use_ssl": true.
Bottomless Abyss MRC supports unencrypted (5000) and SSL (5001); SSL is the better default.
Existing installs are unaffected (their config.json is preserved on update).
Password recovery via security questions. Users can now set up to 3 security
question/answer pairs on their profile (/profile/security-questions). On the Forgot
Password page, accounts with security questions configured are offered a self-service
"Answer security question" path that issues a reset token directly — no sysop required.
Answers are stored hashed (werkzeug); matching is case- and whitespace-insensitive.
Accounts without security questions continue to use the existing sysop-copy-link flow.
New DB table: user_security_answers (auto-created by db.create_all()).
Install wizard simplified. The wizard no longer asks for a separate admin username —
the sysop display name chosen at the start is used as the account login, removing a
redundant prompt that confused fresh installs.
v1.0a2.108 — Door categories + security levels (June 2026)
Game categories (dynamic): New GameCategory DB table replaces the hardcoded
category dropdown. Sysop manages categories at /admin/games/categories — add, rename,
reorder, delete. Default categories seeded on first start: Action, Classic DOS, Puzzle,
RPG, Space, Strategy, Other. Terminal door menu now groups games by category with
separator headers. Web lobby filter dropdown loads from DB.
Min access level per game: New min_access_level field on Game (0=all users,
10=regular, 50=power, 100=sysop). Set it in the game add/edit form. Terminal door menu
and web lobby both hide games the user's access level doesn't reach.