Rewrite mailer_schema.inc — 19 tables now declared via TDBATableSpec
records using FHost.DeclareTable. Includes BLOB column on
p_mailer_partial_inbound and composite PK on p_mailer_link_props.
Per-version MigrateSchema is now a no-op (reconciler handles
ADD COLUMN automatically across SQLite/MariaDB/PostgreSQL).
Tooling:
* Vendor fw_plugin_api + dbapi_* units into sdk/ via `make pull-sdk`.
* Makefile adds fcl-db (sqldb/dbase), paszlib, hash paths.
25 new Pascal units (12,912 lines) converted from Xenia Mailer source:
- CRC-16/32 engine (all 4 variants, verified against test vectors)
- Zmodem: framing engine, send/receive with CRC-16/32, resume, WaZoo 8K
- EMSI: handshake engine with MD5 shared-secret, field parsing, DAT build
- Hydra: bidirectional engine with full rxpkt packet assembly (hex/bin/asc/uue)
- SEAlink: block transfer + YooHoo/2U2 handshake (FTS-0006)
- Session: protocol detection (EMSI/YooHoo/TSYNC/FTS-0001), negotiation
- Period scheduler: bitmask-based time windows (2020-2099)
- Event scheduler: Xenia-style named events with MAT_* behavior flags
- BSO outbound scanner with status tracking
- WaZoo send orchestration (mail bundles, file attaches, requests)
- File request processor with SRIF external processor support
- FAX Class 2 reception (ZFAX/QFX/raw formats) with T.30 parsing
- Modem AT command engine with response parsing, caller ID, MNP detection
- Login script engine (send/expect with sub-expects)
- WFC main loop, nodelist lookup, BBS caller detection
- All types/constants with platform ifdefs (Linux/FreeBSD/Windows/OS2)
WFC screen redesigned to match Xenia's classic layout:
- Blue top bar with system name, AKA address, live clock
- Schedule/Status/Stats/Outbound panels in Xenia's exact arrangement
- Activity panel with modem AT commands/responses
- Session overlay with mail/file counters and transfer progress bar
- CGA/VGA color scheme (cyan labels, green OK, red errors)
- Full real-time via WebSocket — no polling, incremental DOM updates
Events tab rebuilt with proper inline editor (checkboxes for days and
behavior flags, time/duration inputs) replacing prompt() dialogs.
Sessions and Nodes tabs auto-refresh via WebSocket events.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The actual column on bbsnode1 is created_at (standard audit column).
The ALTER TABLE RENAME to imported_at never ran. Use created_at AS
imported_at in the SELECT so the JS field name stays consistent.
Also fix CreateSchema to use created_at matching the audit convention.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 6 service functions to CallFunction that the thin client needs:
- GetPendingCmds: query pending commands, mark assigned, return array
- CompleteCmd: update command status + completed_at
- GetOutbound: read pending outbound packets, base64 encode
- MarkSent: mark outbound packet as sent
- UploadInbound: delegate to HandleInbound for file upload
- ReportMailerStatus: fire EventBus event for WFC live updates
Expand GetExportedFunctions from 10 to 16 entries.
Fix nodelist versions query: use imported_at directly (COALESCE
with non-existent created_at column fails after v0.0.7 rename).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The v1 schema had created_at, the v2 schema has imported_at. The ALTER
TABLE RENAME COLUMN requires SQLite 3.25+ and fails silently on older
versions. Use COALESCE(imported_at, created_at) AS imported_at in the
versions query so it works with both column names. Remove the risky
ALTER TABLE from migration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend (mailer_nodelist.inc):
- Complete rewrite matching old fidonet plugin handlers exactly
- CRC-16 validation from nodelist header (FTS-0005)
- CRC-32 duplicate detection before import
- YYYYDDD version numbering (Year*1000+Day)
- IsNewer logic: only set is_current if version > existing current
- last_insert_rowid() for version ID retrieval
- HandleNodeDiff: full NODEDIFF apply with ZIP support
- ImportNodelistFromFile: inbound toss handler with nodediff detection
- API response formats match old fidonet plugin exactly:
versions: { success, data: [...], total, page, per_page }
search: { success, results: [...], count }
view: { success, version_number, raw_text }
upload/diff: { success, nodes_imported, version_id, version_number }
Schema (mailer_schema.inc):
- Rename created_at -> imported_at in p_mailer_nodelist_versions
- Migration v1->v2 renames column on existing installations
Frontend (web/mailer.js):
- Dedicated Nodelist tab with full UI from old fidonet plugin
- Search with address/sysop/name/location filters and results table
- Upload with ZIP/ARC detection, progress feedback
- NODEDIFF apply with ZIP support
- Version history: always-visible card list, Current/Archive badges,
per-page selector (10/25/50/100/All), pagination, View/Delete
- Raw nodelist viewer panel
- Enter key triggers search
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Makefile: platform-specific unit paths — Linux uses FCL source with
-fPIC, FreeBSD/Windows use pre-compiled units from /opt/fpcup/fpc/units
- CI: delete existing release before creating (handles re-runs)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Schema v1->v2 migration: creates p_mailer_events, coordinator tables
that were added to CreateSchema after initial deployment
- Fix nodelist upload: auto-detect ZIP from filename extension
- Fix nodelist display: JS read r.data.versions instead of r.data
- Fix imported_at -> created_at column name in nodelist info
- Fix WFC stats: direction='in'/'out' to match stored values
- Fix Makefile: move /tmp/paszlib_fpic before FCL source paths
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- HandleWFC: full link status array (pivoted from link_props + outbound)
- Outbound detail per address/packet_type
- ZMH status, scheduler info, echomail stats in today object
- Max poll retries from config for frontend display
- Move mailer_scheduler.inc before mailer_wfc.inc (IsZMH dependency)
- Bump version 0.0.1 → 0.0.3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert web admin from inline HTML to SPA module pattern. Add link
management routes, config defaults, scheduler task stubs, poll command
handling. Major mailer.js rewrite for SPA framework.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Front-end mailer (like FrontDoor/Xenia) — link management, polling,
sessions, nodelist, WFC. Split from monolithic fidonet plugin.
Key design decisions:
- Address-keyed KV schema with typed columns (no migrations ever)
- Audit fields (created/modified by/at) on all tables
- No bbsengine dependency — works standalone
- Nodelist-first link model — protocol auto-detected from flags
- 13 focused include files for maintainability
- Event-driven: fires/listens for echomail.outbound_ready
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>