Skip to content

1.9.10 - #398

Merged
awehttam merged 22 commits into
mainfrom
claudesbbs
Jul 18, 2026
Merged

1.9.10#398
awehttam merged 22 commits into
mainfrom
claudesbbs

Conversation

@awehttam

@awehttam awehttam commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary of Changes

AIO Process Manager (experimental)

  • binktermphp-pm and binktermphp-ctl — the optional Go-based process manager and its companion CLI — are available to download or build from their dedicated repository at github.com/awehttam/binktermphp-pm.
  • This release adds support in the web interface and the admin daemon for driving that external process manager, but only when config/aio.json is present. Without that file, the Admin → BBS Settings → Services menu item does not appear at all, and nothing about a normal install changes.
  • There is currently no migration path or installer integration for binktermphp-pm — it is offered purely for sysops who want to experiment with it ahead of a future, fully supported release.

Netmail Unread Counts

  • Fixed a bug where the netmail unread count and the Unread tab could undercount messages that were correctly delivered to your account but addressed to a nickname or alias rather than your exact username or real name. If your unread netmail count jumps after upgrading, this is why — those messages were already in your inbox, they just weren't being flagged as unread.

Admin Menu Navigation

  • Nested items under Admin in the top navigation (for example Area Management → AreaFix) could become unreachable on narrow browser windows and touch devices. Clicking or tapping a nested submenu heading could silently fail to open it, and once open, the menu could get stuck without letting you scroll down to reach items further down the list. This has been fixed; nested Admin submenus now open reliably and scroll independently of the page.

Login Service Field Validation

  • The POST /api/auth/login endpoint accepts an optional service field used to label how a session was created (for example web or telnet) when displaying it in the Who's Online list. This field is now validated to only contain letters, digits, underscores, and hyphens, up to 20 characters. Requests with a service value outside this format are rejected with a 400 error instead of being accepted.

Echo Area List Mobile Layout

  • Fixed a layout bug on the Echo Areas page where an echo area's tag and description could render as a single word per line, stretching the full height of the screen and making the list unreadable. This was most noticeable on narrow viewports and with longer translated unread-count labels (for example Russian).

Bulk Mark Echo Areas as Read

  • The Echo Areas page (/echolist) now lets you mark an entire echo area as read directly from the list, without opening it first, and lets you select multiple echo areas at once (via a Select toggle and per-row checkboxes) and mark them all as read in one action.

awehttam and others added 22 commits June 29, 2026 17:13
Introduces a Go-based AIO process manager as the primary recommended
deployment method for BinktermPHP, replacing manual systemd/cron setup.

- binktermphp-pm: supervises all BinktermPHP daemons with restart
  policies, exponential back-off, health monitoring (TCP/HTTP probes
  for Postgres and Caddy), and a live ANSI console dashboard
- binktermphp-ctl: companion CLI for start/stop/restart/logs/reload
  and the new set-enabled command via Unix domain socket IPC
- Console dashboard: [s]tart, [S]top, [r]estart, [e]nable/disable
  with status bar feedback; auto-attaches if PM is already running
- Daemon mode (--daemon): re-execs self as detached background process
- Cross-platform: build-tagged platform files isolate Unix-only
  signals (SIGHUP, SIGUSR1, SIGWINCH, Setsid) from Windows
- config/aio.json.example: default service manifest with always-on
  core daemons and opt-in optional services
- makego.cmd / makego.sh: build both binaries to the project root
- Bumps version to 1.9.10

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FrankenPHP replaces the standalone Caddy + PHP runtime with a single
supervised process managed by binktermphp-pm.

- config/Caddyfile.example: ready-to-use FrankenPHP config covering
  php_server (SimpleRouter routing), /ws reverse-proxy to BinkStream
  (realtime_daemon on :6010), gzip/zstd compression, security headers,
  automatic HTTPS via built-in ACME, and commented-out worker mode
- config/aio.json.example: add disabled "frankenphp" service entry
  (frankenphp run --config config/Caddyfile); enable it and remove the
  caddy health check to switch from standalone Caddy to FrankenPHP

Background PHP daemons continue to use the system php binary.
PostgreSQL and BinkStream remain separate supervised services.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a new BBS admin page at /admin/services that lets sysops enable or
disable services defined in config/aio.json without editing the file
directly. Always-on services are shown as locked. Writes are handled
through the admin daemon (get_aio_config / save_aio_config commands) so
the web process never touches config files directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Health checks:
- Add postgres_env check type: opens a real authenticated connection using
  DB_* vars from the root .env file (lib/pq) rather than just probing the
  TCP port
- Add site_verify check type: reads SITE_URL from .env and GETs
  SITE_URL/api/verify, expecting a 2xx response
- .env is parsed once at startup and cached
- Update config/aio.json.example to use the new check types

Shutdown:
- StopAll now accepts a progress callback; in foreground mode the shutdown
  screen prints one [ok]/[killed] line per service as it stops, then
  "Shutdown complete." — previously the screen just cleared and hung silently

Attach / detach:
- q in attach mode now detaches without stopping the daemon (was
  incorrectly sending stop_all to the daemon)
- Q in attach/local mode sends stop_all and shuts the daemon down
- Header adapts: "[q]detach  [Q]stop daemon" when attached, "[q]uit" locally
- Add IsAttached() and StopDaemon() to the Controller interface

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
makego.cmd / makego.sh now build four targets into dist/<os>-<arch>/:
  windows-amd64, linux-amd64, darwin-amd64, darwin-arm64

binktermphp-pm.cmd / binktermphp-pm.sh and binktermphp-ctl.cmd /
binktermphp-ctl.sh are single entry-point wrappers in the project root
that dispatch to the correct dist/ binary for the current platform.
The shell scripts auto-detect OS and arch at runtime and error clearly
if the binary hasn't been built yet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin Services page now shows live runtime status (state, PID, uptime,
  restarts) and exposes start/stop/restart/logs actions per service
- admin_daemon proxies pm commands via forwardToPm(); reads ipc_secret
  from aio.json and performs auth handshake before each request
- pm IPC server validates shared secret on every connection when
  ipc_secret is configured; auth failures are logged and rejected
- Added TCP IPC listener (ipc_addr) so PHP on Windows can reach pm
  without Unix socket support; secret protects the TCP port
- binktermphp-ctl and pm --attach mode both pick up ipc_addr/ipc_secret
  from aio.json automatically via resolveClient()
- Added linux/arm64 build target to makego.cmd and makego.sh
- Fixed badge readability on dark/amber/greenterm/cyberpunk themes:
  neutral badges (disabled state, restart policy, health type) now use
  bg-secondary which all themes explicitly style, instead of bg-light
  with a hard-coded text colour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tools/binktermphp-pm/ and the root-level makego.cmd/makego.sh build
scripts have been moved to the standalone repository at
github.com/awehttam/binktermphp-pm.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Admin dropdown's nested submenus (e.g. Area Management > AreaFix)
were effectively unreachable below the navbar-expand-xl breakpoint:

- The click/tap toggle read the submenu's current computed visibility,
  which a real mouse hover (or a touch tap's synthetic hover) had
  already flipped to visible via the `:hover` CSS rule, so the click
  handler immediately toggled it back closed. Tracked open/closed state
  is now an explicit `.submenu-open` class instead, independent of
  whatever `:hover` happens to be matching.
- Bootstrap's default dropdown auto-close treated any click on a nested
  submenu item as "an item was selected" and closed the whole Admin
  dropdown; `data-bs-auto-close="outside"` keeps it open for clicks
  inside the menu.
- The collapsed `.navbar-collapse` rendered in-flow inside a
  `sticky-top` nav, so once the Admin menu (with submenus) grew taller
  than the viewport, the overflow was pinned off-screen and
  unreachable by scrolling the page. It now scrolls internally via a
  bounded max-height + overflow-y: auto.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds docs/UPGRADING_1.9.10.md covering the Admin nested-submenu
navigation fix from the previous commit, and links it from
docs/index.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…s match

The unread/received netmail filters only matched messages where to_name
equaled the user's username or real_name, but BinkdProcessor::findTargetUser()
can resolve the recipient's user_id via fidonet_address even when to_name is
a nickname that doesn't match either. Those messages appeared under "All"
(matched via user_id) but were silently excluded from "Unread", making the
unread count and tab undercount real unread netmail. Now match by user_id
OR the legacy name+address check, consistently across getNetmail(),
getThreadedNetmail(), the netmail stats API, and the dashboard badge query.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
….json, update AIO docs

The earlier netmail unread-count fix used n.user_id as an unconditional
recipient match, but user_id is the SENDER (not the recipient) for
locally-delivered netmail (same-system user-to-user, or a message to the
sysop), and that row's is_sent stays FALSE forever since nothing gets
spooled. That meant a user's own locally-sent netmail could incorrectly
count as unread in their own account. The user_id match is now excluded
whenever the querying user is identifiable as the sender of that row
(from_name matches them AND from_address is one of the system's own
addresses), so only genuine inbound mail from remote systems benefits
from the recipient-by-address fallback.

Also:
- Admin -> BBS Settings -> Services now only appears when config/aio.json
  exists, since it only applies to installs experimenting with the
  external binktermphp-pm process manager.
- docs/UPGRADING_1.9.10.md and docs/proposals/BinktermPHP-AIO.md updated
  to reflect that binktermphp-pm/binktermphp-ctl now live in their own
  repository (github.com/awehttam/binktermphp-pm) and that this release's
  support for it is experimental, with no migration path yet, plus the
  netmail unread-count fix and its sender-exclusion refinement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ction

The Admin Menu Navigation summary bullet had landed as a stray heading
inside the Netmail Unread Counts detail section instead of alongside the
other Summary of Changes subsections; moved it and synced the TOC anchors.

Also reworded the binktermphp-pm/binktermphp-ctl availability language to
describe where sysops can download or build them rather than framing it
as something removed from this repository, and pointed to
config/aio.json.example as the starting point for config/aio.json.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Explains what PGP/OpenPGP is and why sysops may want to enable it, for readers unfamiliar with public-key cryptography before diving into the feature mechanics.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The service label stored on user_sessions (shown in Who's Online) was
accepted from the client with no character restrictions, allowing
arbitrary strings including HTML metacharacters. Restrict it to
letters, digits, underscore, and hyphen, and reject invalid values
outright instead of silently substituting a default.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The unread-count badge column used flex-shrink-0 with nowrap text,
letting long translated strings claim most of the row width and
squeeze the flex-grow/width:0 title column down to almost nothing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Lets sysops clear low-traffic echo areas without opening them: a
per-row mark-read icon, and a Select mode with a floating bulk-action
bar for marking multiple areas at once. Backed by a new
POST /api/echoareas/mark-read endpoint that reuses the existing
message_read_status/visibility-filter logic from the echomail bulk
read endpoint.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@awehttam
awehttam merged commit d8fb84d into main Jul 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant