7 Commits

Author SHA1 Message Date
a541085a4b 0.7.0: extract TFTNAddress into leaf mb.address unit
Ask 1 from fpc-binkp consumer thread: non-storage libraries
(fpc-ftn-transport, fpc-binkp, future fpc-comet-proto / fpc-emsi,
SQL-backed messaging like Fastway) only need TFTNAddress, not the
full 1041-line mb.types.  Extract to src/mb.address.pas (~90 lines,
only SysUtils) so they can cp a single file into their project.

mb.types continues to uses mb.address so existing callers see the
type transitively -- BUT FPC does not propagate record-field access
through re-export, so consumers that touch TFTNAddress.Zone/Net/
Node/Point directly must add mb.address to their own uses clause.
All 7 in-tree .uni adapters, 2 examples, 5 test harnesses updated.

No behavioural change.  Full suite passes, multi-target build
green (x86_64-linux, i386-{linux,freebsd,win32,os2,go32v2}).
2026-04-21 13:22:53 -07:00
0fe57b846d Rename ma.* -> mb.* namespace (cosmetic, breaking)
Across-the-board rename so the unit prefix matches the repo
name (mb = msgbase).  Brings naming into line with
fpc-ftn-transport's tt.* prefix and avoids the historical
"ma" abbreviation that meant nothing to new readers.

Files renamed via git mv:
  src/ma.{api,events,kludge,lock,paths,types}.pas
    -> src/mb.{...}.pas
  src/formats/ma.fmt.{jam,squish,hudson,msg,pcboard,ezycom,
                      goldbase,wildcat,wcutil}{,.uni}.pas
    -> src/formats/mb.fmt.*.pas

All `unit ma.X` declarations and `uses ma.X` clauses rewritten
to `mb.X` across src/, examples/, tests/.

Suite: 47/47 (read 7, hwm 11, lock 4, pack 4, write 5,
wildcat 5, consumer_round1 5, batch's gone w/ PKT relocation,
plus testutil).

Consumer impact: anyone with `uses ma.api;` etc. needs to
update to `uses mb.api;`. No semantic changes; a search/replace
on the consumer's source tree is the only migration step.
NR's notes (~/.MSGAPI_MSGS.md round 3) align this against
their already-pinned 8130b40; the next NR pin bump rolls in
both this rename and any further work in one step.
2026-04-18 13:19:15 -07:00
6b225fedfc 0.4.0: PKT moves to fpc-ftn-transport (breaking change)
Removes all PKT code from fpc-msgbase. The wire format and its
container concerns now live in the sibling fpc-ftn-transport
library (units tt.pkt.format, tt.pkt.reader, tt.pkt.writer,
tt.pkt.batch).  Pair this commit with fpc-ftn-transport's
0.2.0 (commit 6bb71a6).

Why: the previous "reader here, writer there" split (briefly
landed in 0.3.5) baked in a coupling that didn't survive a
fresh look. The writer reached into fpc-msgbase for types,
the wire format lived in the wrong house, and consumers reading
fpc-msgbase saw "PKT support" that was actually only half-
support. Cleanest split: PKT is a wire format, both directions
belong with the wire-format-aware library; fpc-msgbase becomes
purely real message bases (Hudson / JAM / Squish / MSG /
PCBoard / EzyCom / GoldBase / Wildcat).

Also a cleaner separation-of-concerns story: a BBS that just
reads JAM/Squish never needs fpc-ftn-transport. A pure store-
and-forward node doing only ArcMail unbundle never depends on
storage formats. Each library = one concern.

Removed:
  src/formats/ma.fmt.pkt.pas       -> tt.pkt.format
  src/formats/ma.fmt.pkt.uni.pas   -> tt.pkt.reader
                                      (TPktMessageBase -> TPktReader)
  src/ma.batch.pas                 -> tt.pkt.batch
                                      (TPacketBatch class name unchanged)
  tests/test_batch.pas             -> tests/test_pkt_writer.pas
                                      (consolidated PKT tests)
  examples/example_tosser.pas      -> moves with the batch helper

Reduced in src/ma.types.pas:
  - PacketRecord
  - FlavourType / FlavourTypeSet / DateTimeArray
  - FlagsToFido / FidoToFlags
  - VersionNum (PKT-product-code stamping)
  All moved to tt.pkt.format.

Kept in src/ma.types.pas:
  - mbfPkt enum value (so tt.pkt.reader can register the backend
    with the unified-API factory; consumers still use the
    standard MessageBaseOpen(mbfPkt, ...) shape)

Migration for vendoring consumers:

  before:                      after:
    uses ma.fmt.pkt;             uses tt.pkt.format;
    uses ma.fmt.pkt.uni;         uses tt.pkt.reader;
    uses ma.batch;               uses tt.pkt.batch;
    (no writer surface)          uses tt.pkt.writer;

    TPktMessageBase              TPktReader
    TPktFile, TPktMessage,       (unchanged class names)
      TPktHeaderInfo, etc.
    TPacketBatch                 (unchanged)

Docs sweep:
  - README: PKT row called out as "moved to fpc-ftn-transport";
    TPacketBatch removed from features.
  - docs/architecture.md: layer diagram drops PKT + ma.batch;
    new sibling-library box added for fpc-ftn-transport.
  - docs/attributes-registry.md: PKT column dropped from per-
    format support matrix; pointer to fpc-ftn-transport.
  - docs/API.md: PKT cheat-sheet entry redirects to
    fpc-ftn-transport; TPacketBatch section reduced to a
    "moved" pointer with the new uses-clause shape.
  - docs/ftsc-compliance.md: Type-2 / 2+ / 2.2 / AuxNet rows
    annotated as living in tt.pkt.format.

Suite: 47/47 across 9 programs (was 9 with test_batch; now 9
with the PKT bits dropped from test_consumer_round1 and
test_hwm).  All other tests untouched.
2026-04-18 11:32:42 -07:00
a187c63c10 Lossless message model: Body + Attributes (showstopper fix)
Replaces TUniMessage's 13-field flat record with a strict two-area
model: Body holds only the message text; Attributes holds everything
else (from/to/subject/dates/addresses/MSGID/SEEN-BY/PATH/format-
specific fields) as namespaced key/value pairs.

Why this fix is required NOW: the previous JAM adapter dropped
MSGID, ReplyID, PID, Flags, SEEN-BY and PATH on every Read/Write
through the unified API. A NetReader parity test surfaced it (17/21
pass with 4 kludge failures). All 9 adapters had the same bug. For
tossers and scanners the impact is silent corruption: dropped MSGID
→ dupe storms, dropped PATH → mail loops, dropped SEEN-BY → broken
routing. Three downstream consumers (Fimail's codex-transport branch,
NetReader, future Allfix) had halted integration work pending this
fix. Without it, anyone vendoring fpc-msgbase 0.1 ships with a
known-corrupting adapter.

Design choice: per Ken's call, "message is just the message text;
everything else is an attribute, including from/to/subject/dates."
Same architecture as RFC 822 email (headers + body). Each backend
fills attributes it knows on Read; reads attributes it understands
on Write; ignores unknown attributes silently (RFC 822 X-header
semantics). Forward-compatible -- a new backend (e.g. a planned SQL
message store) just adds its own attribute keys; old backends ignore
them.

Composition is the consumer's job. The library never reassembles
Body + Attributes into kludge-laden display text. A BBS that wants
inline kludges walks Attributes and prepends ^aMSGID etc. to its
own display. A tosser that needs MSGID for dupe detection reads
Attributes.Get('msgid') directly -- no body parsing required.

src/ma.types.pas:
- New TMsgAttribute / TMsgAttributes records with Get/SetValue,
  typed accessors (GetInt/GetBool/GetDate/GetAddr), Has/Remove,
  iteration. Linear-search lookup, fine for the ~30-50 keys per
  message. Switch to hash later if profiling shows need.
- Replaced TUniMessage with the minimal Body + Attributes record.
- New UniAttrBitsToAttributes / UniAttrBitsFromAttributes helpers
  to bridge the canonical MSG_ATTR_* cardinal bitset to/from
  individual `attr.*` boolean keys.
- {$modeswitch advancedrecords} added so records have methods.

src/ma.api.pas:
- New capabilities API: TStringDynArray return type,
  ClassSupportedAttributes (virtual class fn, default empty),
  SupportedAttributes (instance sugar), SupportsAttribute (per-key
  query). Each backend overrides ClassSupportedAttributes with the
  static list of keys it knows. Callers query before setting so a
  BBS UI can hide controls the underlying backend has no slot for.

src/formats/ma.fmt.*.uni.pas (all 9):
- Rewrote each XxxToUni and XxxFromUni for the new model. Read
  populates Attributes with universal/FTSC/format-specific keys per
  the attribute registry (to be published in phase 5). Write reads
  attributes back and writes native form.
- JAM walks SubFields[] for SEEN-BY/PATH/TZUTC/TRACE plus passthrough
  of unknown subfield IDs as `jam.subfield.<id>` for round-trip
  safety. Squish parses CtrlInfo (NUL-separated ^A lines) into
  individual attributes, rebuilds on Write. MSG and PKT (which keep
  kludges inline in body per FTS-1) parse leading ^A lines and
  trailing SEEN-BY/PATH out of the body so TUniMessage.Body is
  always plain user text; on Write they reassemble the on-disk form.
- Each backend ships ClassSupportedAttributes with its key list.

src/ma.batch.pas: PktToUni signature updated to (in,out var) form.

tests/* + examples/*: migrated all callers from Msg.WhoFrom (etc.)
to Msg.Attributes.Get('from'). MakeMsg helpers now use SetValue/
SetBool/SetAddr.

Verified: 24/24 tests pass across all 7 test programs (read,
roundtrip, lock, batch, wildcat, write_existing, pack). Wildcat
walks all 7 vendored conferences clean.

Out of scope (next phases):
- docs/attributes-registry.md publishing the full key list with
  per-format support matrix
- cross-format round-trip + capabilities-driven copy test
- update architecture.md / PROPOSAL.md to reflect the new model
2026-04-17 14:11:15 -07:00
c68a225ad9 Tests + examples: 11 tests passing, full 6-target build matrix
- ma.api: add per-instance FOpCS critical section to serialise Do*
  calls (fixes racing writers that dropped 8/100 messages)
- .uni adapters: momCreate pre-creates empty format files
- example_read/example_write/example_tosser
- tests: test_read (samples), test_roundtrip (all 5 storage formats),
  test_lock (4 threads/100 msgs), test_batch (5 pkts*10 msgs/3 threads)
- run_tests.sh: single-command test runner
- build.sh: per-target binutils (i386-linux, i386-freebsd12, i386-emx)
2026-04-15 08:29:37 -07:00
102df47432 Add JAM, Squish, MSG adapters; case-insensitive *.MSG open; verified vs real samples 2026-04-14 19:38:22 -07:00
800526452a Add Hudson adapter + example_read; writers lock, readers coexist on RO FS 2026-04-14 14:55:32 -07:00