Changelog
Release notes for bafi. Each release is a level-2 heading (## X.Y.Z) matching
version.txt. task release extracts the matching section as the GitHub release
body and refuses to tag if the section is missing. Newest release first.
1.5.1
Fixed
- Comparing values of different types, the classic
{{if gt .count 2}}with a JSON number (float64against the template'sint) or a CSV text value against a number, now explains the cause and the fix (2.0or(toInt .count)) instead of a generic hint. Comparing a list or an object, and a comparison with a missing argument, get their own hints too. - The function reference shows that
add,sub,mul,div,mod,maxandmindrop decimals ({{mul "12.50" 2}}is24) and points to the...ffunctions for decimal values.
1.5.0
Added
- Helpful error messages. Errors name the input or template and, where the parser reports it, the line and column; they show the offending line with a caret, explain the likely cause and link to the matching section of the new troubleshooting page. Covers JSON, YAML, XML and CSV input (with location), BSON and MT940 input, template syntax and execution errors, files and flags. Unknown functions and input formats get a "did you mean" suggestion.
-strictflag: a key missing from the input stops the run with an error that names the key and the template line, instead of printing<no value>.- Warnings on standard error (output unchanged): when the output contains
<no value>, and when a CSV header ends up as a single column because of a wrong-d. - Task-oriented documentation: 16 recipes (XML to JSON, JSON to CSV, REST to SOAP, HTML reports, SQL from CSV, MT940, ...), install, command line, template guide, function reference, troubleshooting and security pages. The sample commands, the function tables and the error examples in the documentation are executed by the test suite.
- The online demo is built from this repository on every release and loads only when used. It shows the same error messages as the CLI.
Changed
- Errors are printed without a timestamp and without internal function names.
- Usage mistakes (no template, no input, unknown flag or
-fvalue,-gkwithout-gq, a stray argument such as an unquoted inline template) print to standard error and exit with code 2. Before, some printed to standard output and exited with 0. Runtime errors still exit with 1. A single trailing-(read standard input) is still accepted. - With
-o, bafi renders the whole result before writing the file: a failing template leaves an existing output file untouched. Before, an error during execution left it half-written. bafi -hshows usage examples and a link to the documentation.- Standard input redirected from a file (
bafi -f json ... < data.json) is accepted; before, only pipes were. - The docs build runs in strict mode, so broken internal links fail it.
Fixed
toXMLwrote&,<,>and quotes unescaped, producing invalid XML; for lists it failed with anerr:text instead.- Files listed in
-i '?files.yaml'now have a UTF-8 byte order mark removed, like a single-ifile. - Some malformed BSON input crashed bafi with a Go stack trace; it is now reported as an input error.
- Several documentation examples were wrong or depended on APIs that no longer exist.
1.4.0
Security
- Lua sandbox. The Lua state no longer exposes
os.execute,os.exit,os.remove,os.rename,os.tmpnameandio.popen. Everything else in the Lua standard library (os.date,os.time,io.open,require, ...) works as before. If yourfunctions.luashelled out through one of the removed functions, it will now fail withluaError: ... attempt to call a non-function object. - Lazy Lua loading.
./lua/functions.luais loaded the first time a template calls{{lua ...}}, not at startup.bafi -v,bafi -hand templates that do not use Lua never execute code from the current directory. - OpenAI key from the environment. The API key is read from
OPENAI_API_KEYwhen-gkis not given, so it no longer has to appear in process listings and shell history.-gkstill works and overrides the variable. - CI hardening. All GitHub Actions are pinned by commit SHA, workflows declare
minimal
permissions, deprecated action versions are upgraded (checkout v7, setup-go v7, setup-python v7, CodeQL v4) and agovulncheckjob runs on every push. Dependabot keeps the pins current. - Release pipeline rebuilt. Releases are built on the GitHub runner with the
Go version from
go.mod(task dist) instead of thego-release.actionDocker image. gofmt/vet, tests and govulncheck gate the release, every asset is listed in aSHA256SUMS.txt, and the release notes are the matchingCHANGELOG.mdsection. go.mongodb.org/mongo-driverbumped to v1.17.10 (GO-2026-5327; the affected GSSAPI code was never reachable from bafi).- Minimum Go raised to 1.27.2 (
go.mod), the release that fixes the stdlib advisories GO-2026-6603 … GO-2026-6617 reported bygovulncheck. Release binaries are built with the same version. - Release archives: new
darwin_arm64(Apple silicon) andlinux_arm64builds next to the existingwindows_amd64,linux_amd64,linux_386anddarwin_amd64. The per-asset MD5_checksum.txtfiles are replaced by oneSHA256SUMS.txt. task releaseonly tags and pushes; the GitHub release is created by CI.- New
## Security notessection in the documentation (trusted templates, no output escaping, CSV formula injection, OpenAI data sharing,randInt).
Added
csvSafetemplate function: prefixes values starting with=,+,-,@, TAB or CR with'to defuse spreadsheet formula injection. Plain numbers such as-5are left untouched.
Fixed
- Lua functions returning a non-string leaked one value on the Lua stack per call.
- A missing or broken
./lua/functions.lua, or a non-string function name, now yields an inlineluaError:in the output instead of aborting the whole run. - Unicode CSV delimiters (
-d) are handled correctly (PR #13). - A malformed
-i ?files.yamlrecord (wrong type or missingfile/label) is reported asfileList[<index>]: ...instead of crashing with a stack trace. - An invalid hex CSV delimiter (
-d 0xZZ) is reported asmapCSV: invalid delimiterthrough the normal error path instead oflog.Fatalf. toXMLrenders[]interface{}slices (e.g. frommustArrayor nested JSON arrays) as<record>elements instead of failing on a type assertion.randIntcannot overflow on extreme bounds such as{{randInt 0 9223372036854775807}}.- An invalid pattern in
replaceAllRegexaborts the template with a readableerror calling replaceAllRegex: error parsing regexp: ...instead of a recovered panic. - An OpenAI response without choices is reported as an error instead of a panic.
Changed
-gqalone now selects OpenAI mode (key from-gkorOPENAI_API_KEY). Without any key it fails withOpenAI API key must be definedinstead of being silently ignored.formatin the-i ?files.yamlfile list is optional; it is detected from the file extension when omitted, exactly like for a single-ifile.randIntusesmath/rand/v2; the explicitrand.Seedat startup is gone (the generator is auto-seeded since Go 1.20).- Version is read from
version.txt(embedded at build time) instead of a constant inmain.go. - New
Taskfile.ymlwithtask build|test|vet|check|vuln|docs|release|clean.task releasetags, pushes and publishes the GitHub release that triggers the CI build. - The changelog is part of the documentation site.
- CI release build runs only on published releases (PR #12).
1.3.0
Reconstructed from git history; this release predates the changelog.
Added
- TOON (Token Oriented Object Notation) output via the
toTOONtemplate function.
Fixed
randInthandles an invalid range and includes the upper bound.