269 lines
12 KiB
Markdown
269 lines
12 KiB
Markdown
# URIT BBS — v0.3.0 Roadmap
|
||
|
||
Status: **Planning**
|
||
Previous: v0.2.0 (steps 10a–17) — telnet, auth, message boards, mail, file libraries,
|
||
bulletins, HTTP file server, inter-node chat, sysop console, sysop guide.
|
||
|
||
---
|
||
|
||
## Step 18 — SSH Support
|
||
|
||
**Priority: 1 — High value, low effort**
|
||
|
||
The config section (`[ssh]`) is already defined and parsed. The session layer
|
||
(`internal/session`) is transport-agnostic — it works on any `net.Conn`. Wiring
|
||
up SSH is primarily a listener and key-management task.
|
||
|
||
### Sub-steps
|
||
|
||
- **18a — SSH listener and host key management.**
|
||
Add an SSH listener to the server using `golang.org/x/crypto/ssh`. Generate a
|
||
host key on first run (or via `urit init`) and store it at the configured path.
|
||
Accept connections, negotiate a PTY channel, and hand the resulting `net.Conn`
|
||
equivalent to the existing `handleConnection` flow.
|
||
|
||
- **18b — Password authentication callback.**
|
||
Wire the SSH password callback to the same `auth.Check` path used by telnet
|
||
login. On successful auth, skip the telnet login prompts and drop the user
|
||
directly into the post-login flow (logon.ans → main menu). Guest access via
|
||
SSH should be configurable (allow/deny in config).
|
||
|
||
- **18c — Terminal handling.**
|
||
Read PTY dimensions from the SSH channel request (replaces telnet NAWS). Map
|
||
SSH window-change requests to the session's terminal size updates. Verify ANSI
|
||
escape passthrough works correctly over the SSH channel.
|
||
|
||
### Notes
|
||
|
||
- The SSH user's identity is known at connection time (unlike telnet, where login
|
||
happens after connecting), so the session lifecycle needs a minor branch: skip
|
||
the welcome.ans → login prompt sequence and jump to the authenticated path.
|
||
- Public key auth is a natural follow-on but not required for the initial
|
||
implementation. Password auth matches the existing BBS credential model.
|
||
- Vendor `golang.org/x/crypto/ssh` into the vendor directory.
|
||
|
||
|
||
## Step 19 — Door Games
|
||
|
||
**Priority: 2 — Highest user-facing impact**
|
||
|
||
Door games are external programs launched from within the BBS, with the user's
|
||
terminal piped through. This was the killer feature of multi-node BBSes in the
|
||
late '80s and '90s. Supporting even a basic door interface opens up a large
|
||
ecosystem of existing door game binaries.
|
||
|
||
### Sub-steps
|
||
|
||
- **19a — Door configuration and menu integration.**
|
||
Add a `[doors]` config section defining available doors: name, command path,
|
||
arguments, working directory, and required SecStatus. Add a `[D]oors` command
|
||
to the main menu (relocate the existing `[D] Download` to another key or make
|
||
it a sub-option). List available doors and let the user select one.
|
||
|
||
- **19b — Dropout file generation.**
|
||
Generate a DOOR32.SYS dropout file before launching the door. DOOR32.SYS is
|
||
the most widely supported modern format and includes: comm type (2=telnet),
|
||
socket handle, baud rate (0 for telnet), BBS name, user info, time remaining,
|
||
and node number. Write the file to a per-node temp directory.
|
||
|
||
- **19c — Process execution and I/O bridging.**
|
||
Launch the door process with `os/exec`, connecting its stdin/stdout to the
|
||
user's telnet (or SSH) connection. Set environment variables that doors
|
||
commonly expect: `DOORNODE`, `DROPFILE`, etc. The door process inherits the
|
||
terminal. On exit, return the user to the main menu. Handle process timeouts
|
||
tied to the user's remaining session time.
|
||
|
||
- **19d — Cleanup and logging.**
|
||
Remove temp dropout files after the door exits. Log door usage (door name,
|
||
user, duration). Handle abnormal door exits gracefully (process crash, timeout,
|
||
signal). Ensure the terminal state is sane after the door returns (re-send
|
||
ANSI reset, re-negotiate telnet options if needed).
|
||
|
||
### Notes
|
||
|
||
- Many classic doors expect a DOS-like environment. Running them may require
|
||
DOSBox or similar on Linux. URIT's role is just the I/O bridge and dropout
|
||
file — the door binary's compatibility is the sysop's responsibility.
|
||
- Native Linux doors (written for systems like Mystic, Synchronet) will work
|
||
more naturally. Some modern door games are written specifically for telnet BBSes.
|
||
- Consider a `door_log` table for tracking door usage statistics.
|
||
|
||
|
||
## Step 20 — Message Threading
|
||
|
||
**Priority: 3 — Model is ready, UI work needed**
|
||
|
||
The `ReplyTo` field exists on the Message model but is not surfaced in the UI.
|
||
Wiring it up gives boards a threaded conversation feel rather than a flat
|
||
chronological list.
|
||
|
||
### Sub-steps
|
||
|
||
- **20a — Reply command in message reader.**
|
||
When reading a message, add an `[R]eply` option that pre-fills the subject
|
||
with "Re: {original subject}" and sets ReplyTo to the parent message ID.
|
||
The compose flow is otherwise identical to posting a new message.
|
||
|
||
- **20b — Thread-aware message listing.**
|
||
Modify the board message list to indicate threading. Two approaches to
|
||
consider: indented tree view (classic Usenet style) or flat list with
|
||
"Re: ..." subjects and a "view thread" command that filters to a single
|
||
conversation. The flat approach is simpler and more BBS-authentic.
|
||
|
||
- **20c — Store support for thread queries.**
|
||
Add `ListMessageThread(boardID, rootMessageID)` to the store interface. This
|
||
returns all messages in a thread (the root plus all descendants) in
|
||
chronological order. Use a recursive CTE in SQLite for efficient traversal.
|
||
|
||
### Notes
|
||
|
||
- Keep the default board view as a flat chronological list — threading is
|
||
additive, not a replacement. Users who don't care about threads should see
|
||
no change in behavior.
|
||
- The HTTP side doesn't currently display messages, but if it ever does,
|
||
threading support in the store will carry over naturally.
|
||
|
||
|
||
## Step 21 — Email Notifications
|
||
|
||
**Priority: 4 — Bridges BBS and modern communication**
|
||
|
||
Lightweight email notifications that pull users back to the BBS when something
|
||
happens that's relevant to them.
|
||
|
||
### Sub-steps
|
||
|
||
- **21a — SMTP configuration.**
|
||
Add an `[email]` config section: enabled flag, SMTP host/port, from address,
|
||
auth credentials (optional), TLS mode (none/starttls/tls). Add an `Email`
|
||
field to the User model for the notification address (set during registration
|
||
or via account settings).
|
||
|
||
- **21b — Notification triggers.**
|
||
Send emails on: new private mail received, reply to a message the user posted
|
||
(requires step 20), and sysop broadcast (optional). Each trigger should be
|
||
individually toggleable per user via account preferences.
|
||
|
||
- **21c — Mail queue and sender.**
|
||
Implement a background goroutine that processes a notification queue. Outbound
|
||
emails are queued (in-memory channel or a database table for persistence) and
|
||
sent asynchronously so they never block the BBS session. Rate limit to avoid
|
||
overwhelming the SMTP relay. Include an unsubscribe link or instructions in
|
||
every email.
|
||
|
||
- **21d — User preferences.**
|
||
Add a notification preferences submenu to the `[A]ccount` command. Let users
|
||
set their email address, enable/disable each notification type, and set a
|
||
digest preference (immediate vs. daily summary). Store preferences in a new
|
||
`user_preferences` table or as additional fields on the user record.
|
||
|
||
### Notes
|
||
|
||
- Keep emails plain text with minimal formatting — matches the BBS aesthetic
|
||
and avoids HTML email complexity.
|
||
- Consider a daily digest mode that batches notifications into a single email
|
||
to avoid spamming active boards.
|
||
- The email address doubles as an account recovery mechanism in the future.
|
||
|
||
|
||
## Step 22 — Automated Backup
|
||
|
||
**Priority: 5 — Operational reliability**
|
||
|
||
A `urit backup` subcommand that snapshots all BBS state into a single archive.
|
||
Designed to be run from cron on unattended systems.
|
||
|
||
### Sub-steps
|
||
|
||
- **22a — Database snapshot.**
|
||
Use SQLite's online backup API (`sqlite3_backup_init`) via the CGo binding to
|
||
create a consistent snapshot of the database while the server is running. This
|
||
is safe for concurrent reads/writes — no need to stop the server. Write the
|
||
snapshot to a temp file, then move it into the backup directory.
|
||
|
||
- **22b — File collection.**
|
||
Copy the screens directory and all library file directories (paths read from
|
||
the library records in the database) into the backup staging area. Skip files
|
||
that haven't changed since the last backup if a `--incremental` flag is set
|
||
(compare mtimes).
|
||
|
||
- **22c — Archive and rotation.**
|
||
Tar/gzip the staged files into a timestamped archive:
|
||
`urit-backup-YYYYMMDD-HHMMSS.tar.gz`. Support a `--keep N` flag that
|
||
automatically deletes backups older than the N most recent. Default output
|
||
directory configurable via `--output` flag or a `[backup]` config section.
|
||
|
||
- **22d — Cron integration.**
|
||
Document cron usage in the sysop guide. Example:
|
||
`0 3 * * * /opt/urit/urit backup -config /opt/urit/config.toml --keep 7`
|
||
The command should exit cleanly with appropriate exit codes (0=success,
|
||
1=partial failure, 2=fatal error) and log to stdout for cron mail capture.
|
||
|
||
### Notes
|
||
|
||
- The backup command connects to the database read-only — it does not need the
|
||
server to be running, but it works safely if it is.
|
||
- Consider adding a `--verify` flag that restores the backup to a temp directory
|
||
and runs a schema integrity check.
|
||
- A `urit restore` subcommand is a natural follow-on but lower priority.
|
||
|
||
|
||
## Steps 23+ — Future Considerations
|
||
|
||
The following features are candidates for future versions. Order and scope are
|
||
flexible.
|
||
|
||
### Full-text search (Step 23)
|
||
|
||
Add keyword search across message boards and mail using SQLite's FTS5 extension.
|
||
A `[/]` command at the board level searches subject and body text. Results
|
||
displayed as a filtered message list. FTS5 is already compiled into the CGo
|
||
binding — the work is creating the virtual table, keeping it in sync with
|
||
inserts, and building the search UI.
|
||
|
||
### File descriptions on telnet (Step 24)
|
||
|
||
The telnet library browser shows filenames but lacks the rich file listing that
|
||
classic BBSes were known for. Add a proper file list display with descriptions,
|
||
sizes, dates, download counts, and uploader names — the traditional columnar
|
||
BBS file list format. The data is all in the store already; this is purely a
|
||
display task.
|
||
|
||
### ANSI auto-detection (Step 25)
|
||
|
||
Detect terminal capabilities during telnet negotiation or ask during login.
|
||
Provide plain-text fallback screens for minimal clients. Add a user preference
|
||
to override detection. Low priority since virtually all modern telnet clients
|
||
support ANSI, but it's a polish item for accessibility.
|
||
|
||
### Rate limiting and connection throttling (Step 26)
|
||
|
||
Add per-IP connection limiting (max N concurrent connections per IP) and a brief
|
||
delay after failed login attempts. The max node count provides a global cap, but
|
||
per-IP limits would prevent a single source from consuming all nodes. Important
|
||
for public-facing systems.
|
||
|
||
### Web admin console expansion (Step 27)
|
||
|
||
Extend the existing `/admin` dashboard with full CRUD for users, boards,
|
||
libraries, and bulletins — a complete browser-based replacement for the telnet
|
||
sysop menu. The middleware, template system, and store methods all exist; this
|
||
is primarily HTML form work. See the step 16 discussion for scope analysis.
|
||
|
||
---
|
||
|
||
## Version Summary
|
||
|
||
| Step | Feature | Priority | Effort |
|
||
|------|------------------------|----------|----------|
|
||
| 18 | SSH support | 1 | Medium |
|
||
| 19 | Door games | 2 | Medium |
|
||
| 20 | Message threading | 3 | Low |
|
||
| 21 | Email notifications | 4 | Medium |
|
||
| 22 | Automated backup | 5 | Low–Med |
|
||
| 23 | Full-text search | — | Low |
|
||
| 24 | Telnet file listings | — | Low |
|
||
| 25 | ANSI auto-detection | — | Low |
|
||
| 26 | Rate limiting | — | Low |
|
||
| 27 | Web admin expansion | — | High |
|