Fidonet Msgbase
FidoNet JAM/Squish/FTS-0001 message base reader — browse areas, read messages, search by sender/address/text
Global Arguments
| Argument | Type | Description |
|---|---|---|
| basePath | string | Path to directory containing message base files |
| Argument | Type | Description |
|---|---|---|
| area | string | Area name (e.g. fido.general) |
| limit | number | Max messages to return |
| offset | number | Skip first N messages |
| Argument | Type | Description |
|---|---|---|
| limit | number | Max messages to return |
| offset | number | Skip first N messages |
| Argument | Type | Description |
|---|---|---|
| sender | string | Sender name to search for |
| limit | number | Max results |
| Argument | Type | Description |
|---|---|---|
| address | string | FidoNet address to match (e.g. 2:5020/1 or 2:5020/1.28) |
| limit | number | Max results |
| Argument | Type | Description |
|---|---|---|
| source | string | Data instance name from a previous search (e.g. sender_John_Doe_a1b2c3, netmail, address_2_5020_1_28_4d5e6f — search instance names carry a trailing 6-hex-digit hash; check the search method's own output for the exact name) |
| folder | string | Obsidian folder for notes |
| Argument | Type | Description |
|---|---|---|
| text | string | Text to search for in message bodies |
| limit | number | Max results |
Resources
Display FidoNet messages from search or area read results
Summarize FidoNet message base results — top senders, areas, date distribution
2026.08.02.1
Real fix for all 9 latent bugs found and pinned by the prior test backfill
(below) -- source edits in extensions/models/fidonet_msgbase.ts, not just
characterization. Valid-message parsing stays byte-identical; the only schema
change is an additive, optional warnings field on the messages resource.
- LB1 (HIGH) --
readAreapath traversal via theareaarg: addedresolveAreaFile(basePath, area, ext), adapted from livejournal-import'snormalizeSegmentsconfinement check, used for all three.jhr/.jdt/.sqdpath builds inreadArea. Rejects any/,\,.., absolute,., or empty area segment withArea '<x>': path traversal rejected, and double-checks the resolved path still lands underbasePath. OnlyreadAreawas a vector -- the fan-out search methods enumerate area files viaDeno.readDir, never from a caller-supplied name. - LB2 (MED) -- Squish frame-chain cycle:
parseSquishMessagesnow tracks visited frame offsets in aSet(plus an iteration cap) and breaks on a revisit instead of looping forever on a craftedA -> B -> Achain. - LB3 (MED) -- silent-skip empty catch blocks:
searchBySender/searchByAddress/searchByText's per-area catches, and a too-short (< 1024-byte).jhrfixed header, now push a message onto a newwarnings: string[]array on the written resource instead of failing completely silently; a good sibling area is still fully searched. - LB4 (MED) --
searchByTextexcluded all Squish areas: added a.sqdbranch mirroringsearchBySender's, so text that exists only in a Squish area is now found. - LB5 (LOW) --
searchByTextdropped JAM areas missing.jdt: a missing.jdtnow sets an empty body and keeps scanning subject/from, matchingreadArea/searchBySender's tolerance, instead ofcontinue-ing past the whole area. - LB6 (LOW) -- Squish truncated-frame OOB reads:
parseSquishMessagesnow checksxmsgOfs + 238 <= sqd.lengthbefore reading the XMSG region and skips (breaks on) a frame that doesn't have the full fixed region present, instead of decoding out-of-boundsundefinedreads as a garbage"0:0/0"address. - LB7 (LOW) -- resource-name slug collision:
searchBySender/searchByAddress/searchByTextnow append a 6-hex-digit FNV-1a hash of the RAW (pre-slugification) query to theirwriteResourceinstance name, so distinct queries that previously collapsed to the identical slug (e.g."John.Doe"vs"John_Doe") no longer overwrite each other's stored results, while the same raw query still produces a deterministic name.readArea/readNetmail/formatForObsidianinstance names are unchanged. - LB8 (LOW) -- JAM subfields carried raw untrimmed bytes: subfield text is
now NUL-trimmed (
.replace(/\0.*/s, "")) to match Squish's XMSG fixed fields and FTS-0001's header fields. Also collapseddecodeText's dead-code high-byte guard (if (slice.some(b=>b>=0x80)) return text; return text;) to a singlereturn text;-- byte-identical, since both branches always returned the same value. - LB9 (LOW) -- unbounded
Deno.readFileinto RAM: addedreadFileCapped(path), whichDeno.stats a file and rejects it before reading if it exceeds a cap (default 256 MiB, overridable via theFIDONET_MSGBASE_MAX_BYTESenv var); used at everyDeno.readFilecall site.readAreathrowsexceeds size cap; the fan-out search methods surface it as awarningsentry instead of dropping the area silently. - Added the model's first
upgrades[]entry (2026.07.16.2->2026.08.02.1, identityupgradeAttributes) -- no breaking schema change. deno.json: bothtestandtest:soaktasks'--allow-envextended fromFC_NUM_RUNStoFC_NUM_RUNS,FIDONET_MSGBASE_MAX_BYTES.quality.yaml: re-stampedratchetfrom a freshswamp extension quality manifest.yaml --jsonrun; header comment updated from "byte-frozen backfill" to "real-fix".- Test suites gained 9 new tests (pin-flips plus new adversarial/contract/ property coverage for the fixes above) -- 59 tests before this change, 68 after; see the test-backfill bullets below for the suites themselves.
Also folded into this release, the STANDARD.md five-suite quality-bar test
backfill that found and pinned the 9 bugs above (wave-4 batch-4a
extension-quality backfill, ext-quality-test-backfill):
- Added
extensions/models/fidonet_msgbase_methods_test.ts(methods, 9 tests),fidonet_msgbase_contract_test.ts(contract-fixture, 15 tests),fidonet_msgbase_adversarial_test.ts(adversarial, 14 tests),
Notes trimmed at a line boundary to fit the registry's 4900-byte per-version cap. Full section: https://github.com/umag/swamp-workspace/blob/d850d8e8372d4c0008c9245959a090b37095de7a/fidonet-msgbase/CHANGELOG.md
Release 2026.07.16.2 — align model versions with manifests
Maintenance release across the @magistr extensions. For most packages this
carries no functional change: the only edit is the model's version: field,
brought back in line with its manifest version so the published model type
version and the package version no longer drift.
Functional changes in this release are limited to:
anime-cron: normalizeTitle now strips a ": subtitle" suffix and a trailing parenthesized year before comparison, fixing dedup false-misses where the torrent title carries a subtitle or year that the AniList romaji does not.
arckit: first publish. Standalone ArcKit port — a 12-phase architecture governance state machine with 65 bundled templates, driven by a bundled skill.
Also tracks three extensions (kaiten, observability-agent, music-library) that previously existed only as untracked working-tree directories, recovered from stashes.
Maintenance version bump. No functional changes.
Added 2, removed 2 reports
Merge pull request #4 from umag/extensions/magistr-grade-a-workspace
extensions: stage 15 @magistr extensions as Grade A workspace dirs + wire CI
- Has README or module doc2/2earned
- README has a code example1/1earned
- README is substantive1/1earned
- Most symbols documented1/1earned
- No slow types (deprecated)1/1earned
- Dependencies pass trust audit2/2earned
- Has description1/1earned
- Platform support declared (or universal)2/2earned
- License declared1/1earned
- Verified public repository2/2earned