13 Commits

Author SHA1 Message Date
850cc65ee3 Milestone 0.3.3: HWM for Hudson + GoldBase + Board context
Adds per-(user, board) HWM for the QuickBBS-family multi-board
formats. The same physical Hudson/GoldBase base file set holds
ALL boards (1..200 for Hudson, 1..500 for GoldBase) in one
LASTREAD.BBS / LASTREAD.DAT file, indexed by user number with
one word slot per board. Caller has to provide both pieces of
context before HWM operations make sense:

- base.MapUser('NetReader', 60001)   - pick a numeric user ID
- base.Board := 5                    - which board this scan is for

src/ma.api.pas:
- New TMessageBase.Board property (longint, default 0).
- Single-area formats (JAM, Squish) ignore it.
- Multi-board formats return -1 from GetHWM when Board <= 0.

src/formats/ma.fmt.hudson.pas:
- New HudsonLastRead record matching QuickBBS LASTREAD.BBS layout.
- TJamBase pattern: FLrStream lazy + EnsureLrStream +
  GetLastRead(user, board) + SetLastRead(user, board, msgnum).
- SetLastRead extends file with zeros to reach the user slot,
  matching QuickBBS convention.
- Uses fpOpen on Unix (same FPC auto-flock workaround as Squish).

src/formats/ma.fmt.goldbase.pas:
- Same shape, GoldBaseLastRead with GOLDBASE_MAX_BOARDS (500)
  slots, file is LASTREAD.DAT.

Both .uni adapters wire DoSupportsHWM/DoGetHWMById/DoSetHWMById
to the new native methods, gating on Board > 0.

tests/test_hwm.pas: 3 new tests covering Hudson + GoldBase:
- TestHudsonRequiresMapUserAndBoard verifies -1 returns when
  MapUser missing, Board missing, or both.
- TestHudsonSetGetPersistence covers two users on two boards
  with cross-session persistence.
- TestGoldBaseSetGet covers a high board number (250) to
  exercise the wider GOLDBASE_MAX_BOARDS range.

Updated docs/architecture.md HWM coverage map: Hudson and
GoldBase moved from deferred to native. EzyCom still deferred
(per-area layout differs); Wildcat/PCBoard still -1.

Suite: 40/40 across 9 programs (test_hwm now 11/11).

NetReader and similar consumers can now register tossers as
high-numbered users (60000+) and walk per-board HWM the way
Allfix has historically done. Tossers coexist with human BBS
users in the same LASTREAD file (different user slots).
2026-04-18 06:12:23 -07:00
20cd593465 Milestone 0.3.2 (closing): HWM docs + coverage map
Documents the HWM API in architecture.md and surfaces it in
README.md's feature list. Includes the auto-bump pattern, the
multi-tenant convention (each tosser registers as a named user
in the same lastread file), and the per-format coverage map.

Coverage decisions for 0.3.x:

  JAM        -- native (.JLR)              [shipped 0.3.0]
  Squish     -- native (.SQL)              [shipped 0.3.1]
  MSG / PKT  -- spec has no HWM, returns -1  [structural]
  PCBoard    -- USERS file too entangled, deferred
  Wildcat    -- WC SDK exposes only per-message MarkMsgRead,
                no per-user HWM primitive; defer until either
                the SDK gains the call or we reverse-engineer
                the user-conference state file
  Hudson     -- LASTREAD.BBS is per-(user, board) and the
  GoldBase     base instance doesn't carry board context;
  EzyCom       needs API design before impl

For deferred formats, GetHWM honestly returns -1 and the caller
falls back to its own state (e.g. NR's dupedb keyed by area).
This matches the "no fakery" principle: don't pretend a format
supports HWM when it doesn't, and don't silently sidecar in a
location consumers can't discover.

The 0.3.0 / 0.3.1 trio gives NetReader native HWM coverage for
the two formats that account for the overwhelming majority of
real-world FidoNet areas (JAM, Squish). Everything else falls
back to dupedb.

No code changes in this commit -- docs only.
2026-04-17 16:02:51 -07:00
1e253e8a78 Phase 5: attribute registry + arch / proposal / README updates
New docs/attributes-registry.md publishes the canonical attribute
key catalog in four tiers:

  1. Universal headers — msg.num, from, to, subject, date.*, addr.*,
     area, board, cost.  Every Fido format carries them.
  2. Canonical attribute bits — attr.private, attr.crash, etc.,
     mapped to/from the FTS-1 attribute word.
  3. FTSC kludges — msgid, replyid, pid, tid, flags, chrs, tzutc,
     seen-by, path, via.  Multi-line keys use #13 between lines.
  4. Format-specific — jam.*, squish.*, hudson.*, goldbase.*, ezy.*,
     pcb.*, wildcat.*, pkt.*, msg.*.  Each backend's namespace.

Plus a per-format support matrix showing which keys each backend
carries. Authoritative source remains each backend's
ClassSupportedAttributes -- the matrix can drift; SupportsAttribute()
is the runtime-correct query.

docs/architecture.md TUniMessage section rewritten:
- Documents the strict two-area model (Body + Attributes only).
- Body holds only the message text, never kludges or headers.
- Library never composes presentation -- consumers walk Attributes
  and assemble their own display.
- Adds the capabilities API section pointing at the registry.
- Removes the stale "kludge lines intact and CR-separated" promise
  the previous adapter implementations didn't honor.

docs/PROPOSAL.md flags the original Extras-bag section as
SUPERSEDED 2026-04-17, points to the registry + architecture docs
as the live design. Original text retained as historical context
since it captures the conversation that drove the redesign.

README.md:
- Features list now leads with the lossless two-area model and the
  capabilities API.
- Adds a Status note flagging 0.2 as a breaking change vs 0.1 with
  a one-paragraph migration sketch (msg.WhoFrom -> Attributes.Get
  ('from'), etc.).
- Documentation index links to the new registry doc.
2026-04-17 14:35:19 -07:00
6181b6abce Rename to fpc-msgbase, scrub false-provenance Allfix references
Project renamed from message_api → fpc-msgbase. Folder, README title,
docs, build.sh, fpc.cfg, and test banners all updated for consistency
with the planned remote at kjgr.io:2222/kenjreno/fpc-msgbase.git.

Also scrubbed claims that backends were "ported from Allfix" or
"match Allfix's msgutil/domsg" — none of this code was ported from
Allfix; it was implemented from FTSC documents and the original
format authors' published specs (jam.txt, squish.doc, pcboard.doc,
EzyCom reference, WildCat 4 SDK headers). Author credits live in
docs/ftsc-compliance.md.

Real interop facts that mention Allfix-the-product stay documented:
the PCB Extra2 sent-bit ($40) Allfix sets when tossing, and the
FTSC-registered product code $EB. These describe external software
behavior we interoperate with, not provenance.

docs/format-notes/hudson.md removed — stale planning doc that
predates the working ma.fmt.hudson backend.
2026-04-17 12:47:43 -07:00
21f3b58096 Add design proposal: plug-and-forget redesign roadmap
Six-week reshape plan: lossless TMsgRecord with Extras bag, ITsmIO
abstraction, TOutboundBatch, single-callback events, explicit locking,
typed exception tree. Captures the cross-project conversation with
NetReader and the byte-agreement cross-verifier as the first
actionable step. Pre-rename baseline.
2026-04-17 11:15:18 -07:00
b79e7fb31d Trim verbose block comments, add docs/API.md, sentinel cleanup on release
- ma.lock.Release now unlinks the .lck sentinel after releasing
  the OS lock (SysUtils.DeleteFile to avoid Windows API collision)
- Unit headers trimmed to standard dev-comment form (purpose only)
- docs/API.md: complete API reference with runnable examples,
  event types, locking semantics, tosser wiring, native-backend
  drop-down pattern, per-format cheat-sheet
- README links to the new doc
2026-04-15 09:34:05 -07:00
d43f996604 Wildcat: full SDK init (InitWCglobal + LoadMakeWild + BTInitIsam); test across 7 conferences
The TWildcatBase.OpenConference was creating a TMsgDatabase without
populating the SDK globals, causing access violations on MwConfig.
Now calls the full Register sequence: InitWCglobal, LoadMakeWild,
BTInitIsam before opening; BTExitIsam + DisposeWCglobal on close.

test_wildcat reads conferences 0..6 from vendored testdata (copied
to /tmp/ma_wildcat so the source tree stays read-only).
2026-04-15 08:41:02 -07:00
443f5fe86f Add FTSC compliance doc + sample data notes 2026-04-14 14:35:52 -07:00
3bc4cb7bec Add ma.api: TMessageBase abstract class, factory, format autodetect 2026-04-14 14:34:50 -07:00
2d9dfb8192 Add ma.events: thread-safe TMessageEvents, hook list, default console log 2026-04-14 13:47:04 -07:00
234cfeabae Vendor WildCat 4 SDK as src/wc_sdk/, add to fpc.cfg search path 2026-04-14 10:45:31 -07:00
ccdaa7dc90 Copy format units from allfix as ma.fmt.* (verbatim, unit names renamed) 2026-04-14 10:44:42 -07:00
426fb677d5 Initial scaffold: layout, fpc.cfg, README, architecture doc 2026-04-14 10:40:56 -07:00