Files
bongo/docs/test-evidence/0.7-r1.md
T
2026-07-26 17:26:37 +02:00

109 KiB
Raw Blame History

Bongo 0.7.0 R1 test evidence

R1 is the implementation and repair pass defined by the release test matrix. This index contains non-secret, reproducible evidence. Disposable credentials, private keys, captured mail, and complete runtime configurations remain outside Git.

Environment

  • Date started: 2026-07-19
  • Source: 50a38f2325293278e3f5e56a4a831c11bf0bc150
  • Host: tiulk, x86-64
  • Kernel: 7.1.3-xanmod1-dist
  • CMake: 4.3.4
  • Ninja: 1.13.2

BLD-01

Result: PASS

Clean GCC 15.3.0 debug configuration and all 360 build steps completed without a compiler warning or link failure.

cmake -S . -B /tmp/bongo-0.7-r1-gcc -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build /tmp/bongo-0.7-r1-gcc --parallel 12
  • CMake cache SHA-256: 286ff1fcbc8b0fdc2949ee1624296bbb79bdc934ddec6eabcde39ae48e6e8a49
  • Runtime configuration: not applicable to this compile-only test.

BLD-04

Result: PASS

All 51 CTest tests passed against the Clang-built binaries.

ctest --test-dir /tmp/bongo-0.7-r1-clang --output-on-failure --parallel 12
  • Result: 51 passed, 0 failed
  • Elapsed test time: 4.43 seconds
  • Source and CMake cache: identical to BLD-03
  • Runtime configuration: isolated fixtures supplied by the tests; no live Bongo configuration was used.

BLD-02

Result: PASS

All 59 GCC CTest tests passed. The suite covered authentication, SQLite transactions, StreamIO search, TLS and PROXY protocol, mail authentication, Sieve, ACME, collector accounts and transport, IMAP, POP3, SMTP, worker jobs, configuration, and Web/DAV discovery.

ctest --test-dir /tmp/bongo-0.7-r1-gcc --output-on-failure --parallel 12
  • Result: 59 passed, 0 failed
  • Elapsed test time: 2.66 seconds
  • Source: ea1e1610a670b233f7e57157d597f0f888282d27 plus the R1 portability repairs recorded by BLD-09.
  • CMake cache SHA-256: 9292384a8e8b073e11c3abc01e5d698ccba449ef625246c0dd120c71ec60fab2
  • Runtime configuration: isolated fixtures supplied by the tests; no live Bongo configuration was used.

BLD-03

Result: PASS

Clean Clang 22.1.8 debug configuration with the same discovered dependencies and all 360 build steps completed without a compiler warning or link failure.

CC=clang cmake -S . -B /tmp/bongo-0.7-r1-clang -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build /tmp/bongo-0.7-r1-clang --parallel 12
  • CMake cache SHA-256: 9f8ca3b62e88c57e9cfd13ed0d6e0072c71dc47cb4fa1a420e329e14bb050920
  • Runtime configuration: not applicable to this compile-only test.

BLD-05

Result: PASS

Commit ed6fc871e344fc7c9a5cd5b6d8ec90486dfca13c was built with GCC, AddressSanitizer, UndefinedBehaviorSanitizer, frame pointers, and the complete test feature set. The installed tree and disposable state/configuration roots were placed below /tmp; the normal bongo.service remained stopped. The protocol session ran as root inside a private user and network namespace, so the real Bongo ports could be exercised without touching host listeners.

cmake -S . -B /tmp/bongo-0.7-r1-asan-live -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON \
  -DCMAKE_C_FLAGS='-fsanitize=address,undefined -fno-omit-frame-pointer' \
  -DCMAKE_INSTALL_PREFIX=/tmp/bongo-0.7-r1-asan-root/usr \
  -DBONGO_CONFIG_DIR=/tmp/bongo-0.7-r1-asan-config \
  -DBONGO_STATE_DIR=/tmp/bongo-0.7-r1-asan-state -DBONGO_USER=root
  • CMake cache SHA-256: 7425b6570598d6bb107066fc6f38b2207731ff12088b965a58d7f3e3c5517296
  • Configuration-set SHA-256: 3f4e84d45cd706cca9bf970419750d0f15bb80addacf884898c5527cb7c344a2
  • CTest: 53 passed, 0 failed in 6.44 seconds.
  • Protocol session: SMTP submission with STARTTLS, SMTPS, IMAPS delivery and SUBJECT search, IMAP STARTTLS, POP3 STLS, and POP3S all passed.
  • The manager and every tested native agent log contained no ASan or UBSan diagnostic. Leak detection was deliberately disabled here because BLD-06 is the separate LeakSanitizer gate.
  • The Web subprocess cannot drop supplementary groups inside the unprivileged user namespace, so it was excluded from this native-agent protocol session; its Python/Web/DAV paths were covered by the sanitizer-loaded CTest suite.

The repair loop found and fixed: empty-array qsort/bsearch undefined behaviour, width-incorrect and unaligned generic JSON integer writes, installed state paths hardcoded outside the configured prefix, incorrect Store-to-IMAP UID mapping for search hits, and a signed high-bit shift in IMAP FETCH flags. Regression tests were added for integer widths, empty arrays, relocated Web state, and Store search-hit parsing.

BLD-06

Result: PASS

Commit 3e9b934ec471ec75f3872558d58f25c710064dab was tested with LeakSanitizer enabled together with ASan and UBSan. Leak detection remained enabled during startup, SMTP delivery, IMAP and POP access, and the complete manager/agent shutdown. The host bongo.service stayed stopped; the protocol session ran in the same private user/network namespace described in BLD-05.

ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:detect_leaks=1:\
fast_unwind_on_malloc=0:malloc_context_size=50 \
UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 \
LSAN_OPTIONS=exitcode=23:report_objects=1 \
ctest --test-dir /tmp/bongo-0.7-r1-asan-live \
  --output-on-failure -E '^python-'

LD_PRELOAD=/usr/lib/gcc/x86_64-pc-linux-gnu/15/libasan.so \
ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:detect_leaks=1:\
fast_unwind_on_malloc=0:malloc_context_size=50 \
LSAN_OPTIONS=exitcode=23:report_objects=1 \
ctest --test-dir /tmp/bongo-0.7-r1-asan-live \
  --output-on-failure -R '^python-'

BONGO_TEST_ROOT=/tmp/bongo-0.7-r1-asan-root/usr \
BONGO_TEST_PASSWORD='<disposable test password>' \
unshare --user --map-root-user --net \
  ./contrib/testing/asan-protocol-session.sh
  • Native CTest: 55 passed, 0 failed. This includes the full Mailutils Sieve syntax/error path and the queue-registration cancellation regression test.
  • Python C-extension CTest: 2 passed, 0 failed with the ASan runtime loaded before CPython.
  • Protocol session: SMTP submission with STARTTLS, SMTPS, IMAPS delivery and search, IMAP STARTTLS, POP3 STLS, and POP3S passed.
  • Manager and agents stopped normally; no process reached the manager's forced-kill deadline.
  • No LeakSanitizer, AddressSanitizer, UBSan, or runtime-error diagnostic was present in the test output or manager/agent log.
  • CMake cache SHA-256: 9696f8805c0f7c50c50ee4e2828600bd8f110b266e49cb72f2a188584f424e4f
  • Configuration-set SHA-256: d6de90aed16ac5c1407fc6dce9a4ee08740c6971d174436eb563df832ec82eed

The repair pass fixed real ownership and lifecycle defects rather than adding sanitizer suppressions: Mailutils Sieve parser/checker lists, Bongo Sieve and GMime objects, Store parser child termination, configuration/JSON/stream allocations, libcurl global cleanup, detached thread-pool lifetime, monitor shutdown, the IMAP busy-thread count, and cancellation of Queue registration while the Queue server is going away. The Mailutils 3.21 fix is carried by the Bongo overlay as commit 61670a4 and was installed for this run.

BLD-07

Result: PASS

Commit 3e9b934ec471ec75f3872558d58f25c710064dab was built with Clang 22.1.8 and ThreadSanitizer. The installed tree used the same private configuration/state roots and isolated user/network namespace as the ASan/LSan protocol session.

CC=clang cmake -S . -B /tmp/bongo-0.7-r1-tsan-live -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON \
  -DCMAKE_C_FLAGS='-fsanitize=thread -fno-omit-frame-pointer' \
  -DCMAKE_EXE_LINKER_FLAGS='-fsanitize=thread' \
  -DCMAKE_SHARED_LINKER_FLAGS='-fsanitize=thread' \
  -DCMAKE_INSTALL_PREFIX=/tmp/bongo-0.7-r1-tsan-root/usr \
  -DBONGO_CONFIG_DIR=/tmp/bongo-0.7-r1-asan-config \
  -DBONGO_STATE_DIR=/tmp/bongo-0.7-r1-asan-state -DBONGO_USER=root

TSAN_OPTIONS=halt_on_error=1 \
ctest --test-dir /tmp/bongo-0.7-r1-tsan-live \
  --output-on-failure -E '^python-'

LD_PRELOAD=/usr/lib/clang/22/lib/linux/libclang_rt.tsan-x86_64.so \
TSAN_OPTIONS=halt_on_error=1 \
ctest --test-dir /tmp/bongo-0.7-r1-tsan-live \
  --output-on-failure -R '^python-'

BONGO_TEST_ROOT=/tmp/bongo-0.7-r1-tsan-root/usr \
BONGO_TEST_PASSWORD='<disposable test password>' \
unshare --user --map-root-user --net \
  ./contrib/testing/tsan-protocol-session.sh
  • Native CTest: 55 passed, 0 failed, including the concurrent atomic and Store logical-lock regression tests.
  • Python C-extension CTest: 2 passed, 0 failed with the Clang TSan runtime loaded before the uninstrumented CPython executable.
  • Protocol session: SMTP submission with STARTTLS, SMTPS, IMAPS delivery and search, IMAP STARTTLS, POP3 STLS, and POP3S passed.
  • Every listener and worker stopped normally. No ThreadSanitizer diagnostic remained in test output or manager/agent logs.
  • CMake cache SHA-256: d20e5508f082782b8867520f3123171de74e76ac2c0004e1f16fa274c1a9f468
  • Configuration-set SHA-256: d6de90aed16ac5c1407fc6dce9a4ee08740c6971d174436eb563df832ec82eed

The repair loop found and fixed real concurrency defects: an AB/BA Store lock order, non-atomic shared agent and listener state, Queue worker teardown while shared tables were still in use, listener socket ownership during shutdown, SMTP client-pool lifetime accounting, the legacy thread-group macro writing to shared caller state, and POP3 freeing a shared GnuTLS context while a worker was still negotiating. The portable atomic implementation is selected through GCC/Clang builtins and CMake links libatomic automatically on targets that require it, including older 32-bit architectures.

After those repairs, the complete ASan/UBSan/LeakSanitizer CTest and live protocol session were repeated successfully. This confirms that the concurrency fixes did not regress the Mailutils Sieve leak repair or introduce new ownership errors.

BLD-08

Result: PASS

Commit f7baf37515d7f963042abd61e00f8a571bb694be was configured and built natively inside an isolated Debian Trixie i386 root with GCC 14.2.0 and GMime 3.2.15. This was a genuine i386 userland rather than an x86-64 build using only -m32. The build used the patched Mailutils 3.21 libraries and archived Debian libsrs2 1.0.18-4 i386 packages. Those historical binaries are test fixtures only; the Trixie release workflow must rebuild libsrs2 from source as specified by BLD-15.

cmake -S /src -B /build -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build /build --parallel 12
ctest --test-dir /build --output-on-failure --parallel 2
  • CTest: 57 passed, 0 failed.
  • CMake cache SHA-256: aed777cda210cc229fac4693e719f4e8c08a685c05c0da99cfdc295062a65a88
  • bongoimap, bongopop3, bongosmtp, bongostore, the Python extension, patched libmu_sieve, and archived libsrs2 were verified as Intel i386 ELF32 objects.
  • The same source then rebuilt without warnings on the x86-64 host against GMime 2.6 with GCC and Clang; both complete CTest runs passed 57/57. This verifies that the GMime 3 compatibility work did not drop GMime 2 support.
  • Valgrind on the i386 Sieve test reported zero errors and no definite, indirect, or possible leaks. The repair fixed a real double-free after mu_message_set_stream() transferred stream ownership; it did not add a suppression.

The repair pass also corrected IMAP header-size conversions so a 64-bit message size is never silently narrowed to the int count accepted by the connection API, and made the HTML sanitizer compatible with Trixie's nh3 0.2.18 while retaining conservative inline-style filtering.

BLD-09

Result: PASS

The complete source was cross-compiled with Clang 22.1.8 for the ARMv5TE soft-float ABI against an isolated Debian Trixie armel sysroot. This is a genuine ARM EABI5 build, not a host build with architecture macros overridden. The sysroot used freshly cross-built copies of the overlay's patched libspf2 and libsrs2 sources. Their LIBSPF2_RFC7208 and SRS2_HAS_SECURE_FREE_SECRETS feature probes both passed during configuration.

cmake -S /home/dbp/bongo-server -B /tmp/bongo-armv5-cross-r1 -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE=/tmp/armv5-bongo-toolchain.cmake \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build /tmp/bongo-armv5-cross-r1 --parallel 12
QEMU_LD_PREFIX=/tmp/bongo-armv5-root2 \
  ctest --test-dir /tmp/bongo-armv5-cross-r1 \
  --output-on-failure --parallel 4
  • Build: all 380 steps completed without a compiler warning or link failure.
  • CTest through QEMU user emulation: 58 passed, 0 failed in 32.41 seconds.
  • CMake cache SHA-256: 8660c5d56d91f58e26aca3d103861adfb42f0a1573fe0d124c26d1998a560969
  • readelf -A reports Tag_CPU_arch: v5TE, ARM ISA, Thumb-1, and the EABI 8-byte alignment rules for the tested server binaries.
  • Source: ea1e1610a670b233f7e57157d597f0f888282d27 plus the documented R1 ARM portability repairs.
  • Runtime configuration: isolated fixtures supplied by the tests; no live Bongo configuration was used.

This pass found and fixed cross-build leakage from LibIcal's host-side CMake package, unsafe packed DNS-result members on strict-alignment ARM, truncated IMAP body offsets on ILP32, and format-width errors in IMAP and Queue. It also enables the 64-bit time_t and off_t ABI on 32-bit Linux, matching modern Trixie armel dependencies and keeping dates beyond 2038 and large mail stores correct.

BLD-10

Result: PASS

ARMv6 soft-float was replaced by ARMv7 hard-float in the release matrix because it exercises a materially different ABI rather than making only a marginal code-generation change from the already tested ARMv5 soft-float baseline. The complete source was cross-compiled with GCC 15.3.0 for ARMv7-A, VFPv3-D16 and the hard-float procedure-call standard against an isolated Debian Trixie armhf sysroot.

The Trixie sysroot was resolved and extracted without installing target packages on the host. Since Trixie no longer supplies libsrs2, the overlay's patched libsrs2 source and patched libspf2 source were both cross-built for the same ARM hard-float ABI. Their security feature probes passed during the Bongo configuration.

cmake -S /home/dbp/bongo-server -B /tmp/bongo-armv7hf-cross-r1 -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE=/tmp/armv7-bongo-toolchain.cmake \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build /tmp/bongo-armv7hf-cross-r1 --parallel 12
QEMU_LD_PREFIX=/tmp/bongo-armv7-root \
LD_LIBRARY_PATH=/tmp/libspf2-armv7-stage:/tmp/libsrs2-armv7-stage \
  ctest --test-dir /tmp/bongo-armv7hf-cross-r1 \
  --output-on-failure --parallel 4
  • Build: all 380 steps completed without a compiler warning or link failure.
  • CTest through QEMU user emulation: 58 passed, 0 failed in 35.80 seconds.
  • CMake cache SHA-256: 8b12f27d448d8de3c7f1b4592b347ea1d8ed7d3f38b705551d8dd345b80b0c16
  • bongoimap, bongosmtp, and bongostore are ELF32 ARM EABI5 PIEs using /lib/ld-linux-armhf.so.3.
  • readelf -A reports ARMv7-A, Thumb-2, VFPv3-D16, and Tag_ABI_VFP_args: VFP registers for Bongo, patched libspf2, and patched libsrs2.
  • Source: ea1e1610a670b233f7e57157d597f0f888282d27 plus the documented R1 portability repairs.
  • Runtime configuration: isolated fixtures supplied by the tests; no live Bongo configuration was used.

BLD-11

Result: PASS

The complete source was cross-compiled with GCC 15.3.0 for AArch64 against an isolated Debian Trixie arm64 sysroot. Trixie does not provide libsrs2, so the overlay's patched libsrs2 and libspf2 sources were both cross-built for the same AArch64 ABI. Their security feature probes passed during Bongo configuration.

cmake -S /home/dbp/bongo-server -B /tmp/bongo-aarch64-cross-r1 -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE=/tmp/aarch64-bongo-toolchain.cmake \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build /tmp/bongo-aarch64-cross-r1 --parallel 12
QEMU_LD_PREFIX=/tmp/bongo-aarch64-root \
LD_LIBRARY_PATH=/tmp/libspf2-aarch64-stage:/tmp/libsrs2-aarch64-stage \
  ctest --test-dir /tmp/bongo-aarch64-cross-r1 \
  --output-on-failure --parallel 4
  • Build: all 380 steps completed without a compiler warning or link failure.
  • CTest through QEMU user emulation: 58 passed, 0 failed in 20.76 seconds.
  • CMake cache SHA-256: 97a2c242b187c4d2f3a1f9b7d67addd8e248cd37e27ef12b7857e85a03ab9ab2
  • bongoimap, bongosmtp, and bongostore are ELF64 AArch64 PIEs using /lib/ld-linux-aarch64.so.1; patched libspf2 and libsrs2 are ELF64 AArch64 shared libraries.
  • Source: ea1e1610a670b233f7e57157d597f0f888282d27 plus the documented R1 portability repairs.
  • Runtime configuration: isolated fixtures supplied by the tests; no live Bongo configuration was used.

BLD-12

Result: PASS

CPack generated the native TGZ binary package, which was extracted into a new empty staging root. Its /usr/local tree and a disposable /var/lib/bongo were then mounted only inside a private user/mount namespace so the installed Python extensions could be loaded at their configured paths without modifying the host installation.

cpack -G TGZ --config /tmp/bongo-0.7-r1-gcc/CPackConfig.cmake \
  -B /tmp/bongo-cpack-r1-fixed
mkdir -p /tmp/bongo-cpack-r1-root3
tar -xzf /tmp/bongo-cpack-r1-fixed/bongo-0.7.0-Linux.tar.gz \
  -C /tmp/bongo-cpack-r1-root3
BONGO_CPACK_ROOT=/tmp/bongo-cpack-r1-root3/bongo-0.7.0-Linux \
unshare --user --map-root-user --mount \
  ./contrib/testing/cpack-stage-smoke.sh
  • Package: bongo-0.7.0-Linux.tar.gz, 1,035 regular files.
  • Package SHA-256: af00479ac617f98c95be4739e3d74c8cc8ef381b5733e5bda363b1bccf8a33c9
  • CMake cache SHA-256: 9292384a8e8b073e11c3abc01e5d698ccba449ef625246c0dd120c71ec60fab2
  • All 1,115 archive members use relative, non-traversing paths.
  • All 24 symbolic links resolve inside the staged installation.
  • All 37 ELF objects have a complete dependency tree when the staged Bongo library directory is used; none resolves a Bongo library from the host.
  • The staged bongo, bongo.configuration, bongo_web, libbongo, calendar, external-account, QR-code, and authentication-security Python modules load successfully without writing bytecode into the package tree.
  • Source: commit 9b3c958c plus the XPL initialization repair described below.
  • Runtime configuration: disposable state only; no live Bongo configuration or service was used.

The first staging run found that importing _calendar and _external_accounts in one process called XplInit() twice. libgcrypt rejects changing its seed-file configuration after initialization and aborted. XPL initialization is now guarded by pthread_once, detects libgcrypt initialized by another library, and has a dedicated repeat-initialization regression test. The complete host suite passed 59/59 after the repair.

BLD-13

Result: PASS

CPack generated a source-only TXZ named bongo-0.7.0.tar.xz; neither the archive nor its single top-level directory contains -Linux or -linux. The archive was extracted into a new directory and configured and compiled from that extracted copy to prove that the filtering did not remove a required source.

cpack -G TXZ \
  --config /tmp/bongo-0.7-r1-gcc/CPackSourceConfig.cmake \
  -B /tmp/bongo-source-r1
tar -xJf /tmp/bongo-source-r1/bongo-0.7.0.tar.xz \
  -C /tmp/bongo-source-r1-root
cmake -S /tmp/bongo-source-r1-root/bongo-0.7.0 \
  -B /tmp/bongo-source-r1-build -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=OFF
cmake --build /tmp/bongo-source-r1-build --parallel 12
  • Source archive SHA-256: c11c4baaacdc0205d02a846277883c3223795c3b4d521f9fe1f7c4d212acd635
  • Extracted-build CMake cache SHA-256: 61bf4b5f556b5c7c9c51f67eeac7754d0a29cd902f3a8aa639146d3092819072
  • Archive contents: 1,880 members, 1,752 regular files, one top-level directory, and no symbolic links.
  • No absolute or parent-traversing archive paths were present.
  • No Git/SVN/Hg, Codex/agent, CMake build/cache, Python cache, private-key, credential-token, database, core, or log artifacts matched the release checks.
  • The extracted source completed all 244 non-test build steps without a compiler warning or link failure.
  • Source: commit 9b3c958c plus the XPL initialization repair recorded by BLD-12.
  • Runtime configuration: not applicable to this source-package test.

BLD-14

Result: PASS

The Gentoo live ebuild was rebuilt from commit 806bdf789d79f41031f14aeb1a40264ac7fa07ee, ran its test phase, and merged successfully on the native amd64 test host. The active package configuration was debug fail2ban test with Python 3.14.

emerge --oneshot '=mail-mta/bongo-9999::bongo'
pkgcheck scan --cache-dir /tmp/pkgcheck-bongo \
  --exit error '=mail-mta/bongo-9999'
qcheck -v mail-mta/bongo
  • The test-enabled build, install, and merge completed without a Portage QA notice or internal package collision.
  • pkgcheck completed with status zero for the live ebuild.
  • qcheck verified all 1,445 installed package entries.
  • The installed image contains 303 compiled Python bytecode files as well as the systemd units, tmpfiles configuration, man pages, translations, Web assets, Fail2ban files, zone information, and examples.
  • No package entry is installed below /usr/var, /usr/etc, or /var/run.
  • The sendmail, mailq, newaliases, and /usr/lib/sendmail compatibility links are all owned by mail-mta/bongo-9999 and resolve to bongo-sendmail.
  • scanelf found no unresolved dependency among the installed Bongo server executables and versioned shared libraries.
  • bongo.service remained inactive throughout package QA, as required for this non-lifecycle test.

Runtime configuration: the installed development configuration was not started or modified by this package test.

BLD-15

Result: PASS

Gitea Actions run 2537 rebuilt Bongo and all maintained patched dependencies in a Debian Trixie amd64 container. The workflow completed successfully in 21 minutes 9 seconds, including dependency regression tests under Valgrind, the Bongo build, lintian --fail-on error, package installation, and the installed-package smoke test.

unzip -t bongo-0.7.0-dev9e02056-debian-trixie.zip
unzip -q bongo-0.7.0-dev9e02056-debian-trixie.zip -d bundle
(cd bundle/bongo-0.7.0-dev9e02056-debian-trixie && \
  sha256sum -c SHA256SUMS)
dpkg-source -x sources/mailutils/mailutils_3.19-1+bongo1.dsc mailutils
dpkg-source -x sources/libspf2/libspf2_1.2.10-8.3+bongo1.dsc libspf2
dpkg-source -x sources/libsrs2/libsrs2_1.0.18-4+bongo1.dsc libsrs2
dpkg-source -x sources/bongo/bongo_0.7.0-1.dsc bongo
  • Source: commit 9e02056ba17a9edf67574da792d1000bcf839ab0.
  • Build environment: Debian Trixie amd64, GCC 14.2.0; the four source buildinfo files record their architecture, compiler, and package set.
  • Release archive: bongo-0.7.0-dev9e02056-debian-trixie.zip, SHA-256 e0bf2e8d4273621c2799940ca4b84fc104d159cdc2eff09a3f14560a4bb75479.
  • ZIP integrity passed and all 57 entries covered by the internal SHA256SUMS verified. The bundle contains 36 binary packages and 21 source artifacts.
  • The complete, unsigned local source packages independently extracted: Mailutils 1:3.19-1+bongo1, libspf2 1.2.10-8.3+bongo1, libsrs2 1.0.18-4+bongo1, and Bongo 0.7.0-1. Their upstream archives, Debian patch archives, .dsc, source .changes, and source .buildinfo files are all present.
  • Mailutils and libspf2 retain the official Trixie binary-package splits. The rebuilt archived libsrs2 source retains libsrs2-0 and libsrs2-dev and adds the historical srs2 daemon package; no archived binary was used.
  • Bongo's source buildinfo pins the three patched development packages. The resulting SMTP/Sieve ELF objects directly require the expected libspf2.so.2, libsrs2.so.0, libmailutils.so.9, and libmu_sieve.so.9 SONAMEs.
  • The bundle installer verifies checksums and exact patched package versions, then holds only the patched dependency libraries; Bongo itself remains upgradeable.

Runtime configuration: the workflow used only its disposable Trixie container and did not install or alter the live test host.

BLD-16

Result: PASS

Two clean GCC 15.3.0 debug builds exercised crossed prefix/library layouts: a distribution /usr install using lib64, and a self-contained /usr/local install using lib. Both were installed below empty DESTDIR roots and their compiled defaults, generated units, tmpfiles declaration, ELF runpaths, directory trees, and symbolic links were audited.

cmake -S . -B /tmp/bongo-bld16-usr -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON \
  -DCMAKE_INSTALL_PREFIX=/usr -DLIB_DIR_NAME=lib64
cmake --build /tmp/bongo-bld16-usr --parallel 12
ctest --test-dir /tmp/bongo-bld16-usr --output-on-failure --parallel 12
DESTDIR=/tmp/bongo-bld16-usr-root \
  cmake --install /tmp/bongo-bld16-usr --prefix /usr

cmake -S . -B /tmp/bongo-bld16-local -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=OFF \
  -DCMAKE_INSTALL_PREFIX=/usr/local -DLIB_DIR_NAME=lib
cmake --build /tmp/bongo-bld16-local --parallel 12
DESTDIR=/tmp/bongo-bld16-local-root \
  cmake --install /tmp/bongo-bld16-local --prefix /usr/local

systemd-tmpfiles --create --dry-run \
  --root=/tmp/bongo-bld16-tmpfiles-root \
  /tmp/bongo-bld16-usr/init/bongo.conf
  • Source: commit 58d2e89 (Move volatile PID files under run).
  • Full CTest result: 72 passed, 0 failed in 3.40 seconds.
  • /usr cache SHA-256: f56949bfc8fa2a0963c3460a96db3e61bb9f4a274ddfc4370f2d9e7c56025e48.
  • /usr/local cache SHA-256: 5f86eafad069052a4fd7e04b523f6bf56f1f38becab410598cc0df7f8197637d.
  • Both staged trees contain 1,064 regular files or symbolic links. The first uses /usr/lib64, /etc/bongo, and /var/lib/bongo; the second uses /usr/local/lib, /usr/local/etc/bongo, and the same FHS state path.
  • No staged directory appeared below /usr/etc, /usr/var, /usr/local/var, /var/run, or /run. Runtime and persistent directories are declarations created after installation, not package payload.
  • Generated tmpfiles data passed systemd-tmpfiles parsing and declares /run/bongo separately from /var/lib/bongo. The manager, agent recovery flags, administration status, and managed LDAP PID paths all compile to the volatile directory.
  • All installed ELF runpaths match the selected lib64 or lib directory; no build-directory runpath was present. All 26 library symlinks in either staged tree are relative and resolve within their selected library root.

The initial audit failed because PID and agent recovery files still used the persistent /var/lib/bongo/work directory. The repair adds the configurable BONGO_RUNTIME_DIR (default /run/bongo) while keeping diagnostic traces and ring logs in persistent state.

Runtime configuration: isolated staging roots and a dry-run tmpfiles root; the live Bongo installation and service were not modified.

BLD-17

Result: PASS

The Debian Trixie workflow now runs a destructive package lifecycle test only inside its disposable build container. It installs the freshly built Bongo package, creates distinct configuration, private-key, user-mail, system-Store, and queued-message markers, and verifies all five after a same-version reinstall. The test then repacks the identical payload with the unpublished test-only version 0.7.0-1+lifecycle1 and installs it through APT so that dpkg's real upgrade maintainer-script path is exercised.

Normal removal deleted the program payload while retaining Debian conffiles and every site-created marker. Purge then deleted the package-owned Fail2ban filter and disabled jail template, removed Bongo from the package database, and still preserved /etc/bongo and /var/lib/bongo. This matches the now documented safe-removal policy; /run/bongo remains explicitly volatile and is not treated as recoverable state.

The package test also found and removed a redundant hand-written systemd-tmpfiles invocation from postinst. Debhelper's generated sequence already performs the operation once and correctly handles DPKG_ROOT.

  • Source: commit 00b7cc3f3a945d744dafd0165e47dc9a67e72c01.
  • Gitea Actions: Debian Trixie workflow run 2543, success in 21m05s.
  • Build environment: Debian Trixie amd64, GCC 14.2.0, CMake 3.31.6.
  • Build date: 2026-07-21 10:48:28 UTC.
  • Release archive: bongo-0.7.0-dev00b7cc3-debian-trixie.zip, SHA-256 087011d70582c672d72d6a30c3d98276bc35764e4195e1734c423e308ebcb31d.
  • Package configuration: Bongo 0.7.0-1, Mailutils 1:3.19-1+bongo1, libspf2 1.2.10-8.3+bongo1, and libsrs2 1.0.18-4+bongo1, as recorded by the bundle manifest and source buildinfo.

Runtime configuration: disposable marker files in the isolated Gitea job; the live Bongo installation and service were not modified.

BLD-18

Result: PASS

A clean GCC 15.3.0 debug build enabled the GNU linker --no-undefined check for every Bongo shared library and loadable module. The repair removed legacy circular object ownership between connio, util, and msgapi, made each shared object declare its actual direct dependencies, and removed the artificial dependency lists previously needed by the connio tests. The complete 72-test suite then passed in 2.46 seconds.

cmake -S . -B /tmp/bongo-bld18-clean-build -G Ninja \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON \
  -DCMAKE_INSTALL_PREFIX=/usr -DLIB_DIR_NAME=lib64
cmake --build /tmp/bongo-bld18-clean-build --parallel 12
ctest --test-dir /tmp/bongo-bld18-clean-build \
  --output-on-failure --parallel 12
DESTDIR=/tmp/bongo-bld18-final-root \
  cmake --install /tmp/bongo-bld18-clean-build --prefix /usr
  • Source repair: commit 2085fbfbab0b598f5b722be508de11e6913d9c68. The package retry commit ce75ba3a95f94c5e649f713749b498abf9d52cdd is intentionally empty and contains the identical source tree.
  • Clean CMake cache SHA-256: 50c4181e8f96cff15f1259293decfe03073f502495e87f43ab02c25cb10aefac.
  • The staged installation contains 1,064 files or symbolic links. All 20 ELF shared objects were checked with ldd -r; none reported a missing library or undefined symbol.
  • All 13 versioned Bongo shared libraries carry the matching libbongo*.so.0 SONAME. Each development link resolves through a relative .so -> .so.0 -> .so.0.7.0 chain within the selected library directory.
  • The seven additional loadable authentication and Python extension modules also pass the dependency audit without relying on the loading executable to provide unresolved Bongo symbols.
  • Gitea Actions run 2549 repeated the full Debian Trixie dependency, Bongo, Lintian, installed-package, and package-lifecycle build successfully in 21 minutes 8 seconds.
  • Release archive: bongo-0.7.0-devce75ba3-debian-trixie.zip, SHA-256 579aa9903a3e98e029596749f7ea7ddd574aac95dfa3ef2c6365b6241f337f97. The ZIP test passed and all 57 files listed in its internal SHA256SUMS verified.

The first remote attempt, run 2546, failed before checkout while its Actions runner was overloaded. It spent its whole lifetime in Set up job and produced no build log; run 2549 is the unchanged, successful retry.

Runtime configuration: isolated staging roots and a disposable Debian Trixie job; the live Bongo installation and service were not modified.

BLD-19

Result: PASS

A clean GCC 15.3.0 installation audit verified that the source and installed trees contain the complete documentation, localization, Web UI, service, and configuration payload. The staged installation contains 1,106 regular files or symbolic links, and the complete 72-test suite passed in 2.85 seconds.

  • Source: commit faf4f706c5c92aa78550bf9b7e2afa6132336573.
  • Clean CMake cache SHA-256: f39024ab6b8a2d5625fab564667187895d7f0ec66d322e85faec00b04d5e231b.
  • All 199 Web static files are installed byte-for-byte, together with all 25 Markdown documentation files and all 10 ACME, antispam, and reverse-proxy examples.
  • Nine section-1 and 14 section-8 manual pages are installed. All 23 render successfully with groff, and every one of the 22 installed /usr/sbin executables has a same-name manual page.
  • Five compiled message catalogs are installed: German, French, and Brazilian Portuguese for the Web UI plus French and Brazilian Portuguese for the core tools. Every catalog decodes successfully with msgunfmt.
  • The three installed systemd units pass systemd-analyze verify. The staged ELF dependency audit also reports no missing library or unresolved symbol.
  • Gitea Actions run 2552 repeated the Debian Trixie build, tests, Lintian audit, package lifecycle, and development-release publication successfully in 21 minutes 24 seconds.
  • Release archive: bongo-0.7.0-devfaf4f70-debian-trixie.zip, SHA-256 9a66e50b0c85df53ad456a65625c846b2fdfd7f82e98a8605a931d24583b0a41. Its ZIP structure is valid and all 57 entries in the internal SHA256SUMS verify, including 36 binary Debian packages and 21 source-package files.

Runtime configuration: isolated staging roots and a disposable Debian Trixie job; the live Bongo installation and service were not modified.

CFG-01

Result: PASS

The real curses setup wizard was driven from start to finish in a 100-column by 24-line pseudo-terminal. DNS discovery and scanner probes were made deterministic, and every configuration, alias, TLS, DKIM, DMARC, and ACME path was redirected below /tmp/bongo-cfg01-root. The test stopped at the final confirmation without calling the installer.

The default flow selected Apache reverse-proxy mode with HTTPS public URL, loopback-only trusted proxy access, IMAP, POP3, ManageSieve, and authenticated submission. ACME, legacy TLS, internal relay, LDAP, ClamAV, and SpamAssassin remained disabled until explicitly selected. The generated scenario used mail.example.test, 192.0.2.10, and example.test; all generated documents passed model validation with no errors.

The terminal transcript contains neither of the previously observed merged prompt fragments (WeYesdirect and MaNo proxy). The layout unit checks also place choices below both single-line prompts and multiline confirmation summaries, including scrolling in a 60x12 terminal.

  • Source: commit faf4f706c5c92aa78550bf9b7e2afa6132336573.
  • Terminal: TERM=xterm-256color, 100 columns by 24 lines.
  • Result: one complete wizard pass, zero validation errors, zero writes to the live Bongo configuration or Store.

Runtime configuration: isolated pseudo-terminal and temporary configuration root; the live Bongo installation and service were not modified.

CFG-02

Result: PASS

The current Gentoo live ebuild was installed over an already configured Bongo test installation. The setup installer was then repeated with the same host, domain, and administrator account. It reused the existing TLS certificate and key, printed Complete., and exited with status zero. This exercises the real Store and privilege transition rather than a redirected staging root.

Before and after the repeated setup, SHA-256 digests were recorded for all 14 documents in config.d, the default alias document, both TLS files, the Store databases of test1 and test2, and an existing message in test2's mailbox. All 20 files remained byte-identical. The user list also remained exactly admin, test1, and test2.

The setup path was additionally run twice under AddressSanitizer in an isolated network and staging root. Both runs completed with status zero and no sanitizer diagnostic. The regression fixed an uninitialised stack-based BongoAgent whose shutdown path could wait on random monitor state and free a random monitor pointer.

  • Source: commit 0e06501c72a1281e326cef265a40ef31de3cb182.
  • Package: mail-mta/bongo-9999::bongo, Gentoo debug build.
  • Automated regression suite: 74 of 74 tests passed.
  • Result: one repeated live setup and two isolated ASan repetitions passed; configuration, credentials, TLS material, users, Store databases, and the existing message were preserved.

Runtime configuration: the Bongo service remained stopped during setup and data-integrity verification.

CFG-03

Result: PASS

The installed administration TUI loaded the operative Store and changed the worker polling interval from 30 to 31 seconds. The resulting suffixless file and the Store document both contained 31. Repeating the edit restored both to 30. During the first pseudo-terminal run, a terminal which did not implement cursor-visibility control exposed a fatal curs_set() assumption. Commit b4526b95580565722b235de7023a8e2dec00ad0b makes cursor visibility a best-effort operation and adds a regression test for that terminal class.

bongo-admin config check accepted both states and reported only the two expected policy warnings for this disposable configuration. bongo-admin config sync completed after each change and requested a manager reload. The systemd service remained active and the manager retained PID 584414 and its original start timestamp across the final reload.

The injected Store-write failure regression was extended to assert complete transaction rollback. It now verifies restoration of both earlier Store documents and every local configuration file, while the existing scanner activation test verifies restoration when a manager reload fails. The complete configuration-model suite passes with these checks at commit 732300efd68e6da5e2121e50d418d94defca30b3.

  • Live source: commit b4526b95580565722b235de7023a8e2dec00ad0b.
  • Rollback regression: commit 732300efd68e6da5e2121e50d418d94defca30b3.
  • Live edit: worker.poll_interval_seconds 30 to 31 to 30.
  • Result: check, interactive edit/save, file/Store synchronization, rollback, and manager reload passed without restarting or failing the service.

Runtime configuration: local Gentoo debug installation with Bongo active under systemd; no release tag was created.

CFG-04

Result: PASS

The complete installed setup wizard was run as root against the disposable Gentoo test installation with SMTP, submission, IMAP, POP3, ManageSieve, the rate-limited internal relay, ClamAV, SpamAssassin, and outgoing DKIM signing enabled. It reused the existing TLS certificate and key, generated a new 2048-bit DKIM key for bongo.test, persisted the DMARC guidance, and created the ACME credential directory even though automatic certificate issuance was left disabled.

The resulting layout contains exactly 14 suffixless documents in config.d and one suffixless default fragment in aliases.d; neither directory contains a .json filename. The security directories ssl.d, dkim.d, dmarc.d, and acme.d are owned by root:bongo with mode 0750. Private TLS and DKIM keys and the DMARC state use mode 0640. Public certificates and DKIM DNS material use mode 0644. The generated SMTP configuration points at /etc/bongo/dkim.d, uses selector bongo, and enables outgoing DKIM signing.

bongo-admin config check accepted the complete configuration. Its sole warning is expected for the intentionally direct HTTP test listener. After a systemd restart, all configured native agents, both scanner agents, the scheduler worker, and the Python Web agent remained active; the Web agent reported that it was listening on 0.0.0.0:8080.

  • Live source: commit b4526b95580565722b235de7023a8e2dec00ad0b.
  • Mail identity: mail.bongo.test, hosted domain bongo.test.
  • Result: suffixless configuration and alias files, secure TLS/DKIM/DMARC/ACME layout, Store validation, and complete service startup passed.

Runtime configuration: local Gentoo debug installation. The generated keys are test-only material and no release tag was created.

CFG-05

Result: PASS

All historical source trees and development branches were searched before the migration test. The original Web configuration name web, its later Python 3 name bongo-web.json, the authentication file bongo.conf, and the Store TLS pair osslcert.pem/osslpriv.pem are the historical external configuration names which need explicit migration. The operative post-0.7 Web configuration is only the suffixless /etc/bongo/config.d/web; no historical filename is a runtime fallback.

Isolated migration tests imported both historical Web names independently, converted the authentication settings, moved the complete TLS pair with the required key permissions, and wrote every current Store and alias document. The command-line test verifies that bongo-admin migrate prints every source and destination path. A second invocation is refused after config.d exists. Ambiguous Web files, incomplete TLS pairs, and unknown legacy recipient mappings are rejected. An injected pre-existing backup collision after the first file move restored both source files, preserved the existing backup, and removed every newly written configuration document.

  • Source: commit f28dd0662ccc5696d964b4719497d3bdd003cbd1.
  • Compiler: GCC 15.3.0 (Gentoo Hardened 15.3.0 p8), x86-64.
  • Template checksum: SHA-256 6c20ef6e0b5aaecb29cbcf4d931aaa3bae5d056e1299a78b98b7edcdde5b1987.
  • Target: Linux 7.1.3-xanmod1-dist, 2026-07-22.
  • Focused result: 36 of 36 configuration storage and CLI tests passed.
  • Complete result: 81 of 81 CTests passed.

Runtime configuration: temporary configuration, state, TLS, and backup roots; the live Bongo Store and /etc/bongo were not modified.

CFG-06

Result: PASS

Suffixless files below aliases.d were tested with an aliases object only, a domains object only, and both objects in one fragment. Domain-specific address aliases override the global aliases without removing them. Domain options accept the named local-part, full-address, and domain-name recipient mappings which the manager translates to Store values 0, 1, and 2.

The validation path also accepted an internationalized alias domain when its IDNA2008 A-label matched the hosted domain. It rejected conflicting mappings split across files, aliases for unhosted domains, numeric mapping values in the new format, and unsupported values imported from the historical Store format. Per-domain DMARC report aliases resolved to the intended user independently of the global fallback.

  • Source: commit af37168e370764c5ee557e1262b0a5296ab528e3.
  • Compiler: GCC 15.3.0 (Gentoo Hardened 15.3.0 p8), x86-64.
  • Template checksum: SHA-256 6c20ef6e0b5aaecb29cbcf4d931aaa3bae5d056e1299a78b98b7edcdde5b1987.
  • Target: Linux 7.1.3-xanmod1-dist, 2026-07-22.
  • Result: eight focused alias validation, migration, IDNA, conflict, and DMARC routing tests passed; the complete 81-test suite remained green.

Runtime configuration: isolated temporary alias and configuration trees; the live aliases and Store documents were not changed.

CFG-07

Result: PASS

The installed scanner editor has one adjacent backup for each edited scanner configuration. Comparing the live Gentoo files with those backups showed only the intended changes: ClamAV retained its distribution configuration while moving its root-level PID file beside the private socket and adding bounded loopback TCP settings; SpamAssassin retained its existing process options and added only the loopback listener, port, allowed address, and IPv4 selection. The operative Store enables both scanner agents and points them at 127.0.0.1:3310 and the default loopback spamd endpoint. spamc -K returned a valid SPAMD/1.5 0 response.

The isolated transaction suite covered Gentoo/OpenRC and Debian/systemd layouts. Repeating both editors is byte-idempotent. Failed rule download occurs before any scanner file is edited. Failed scanner probing restores the original file, removes newly created systemd drop-ins, returns enabled/active service state to its snapshot, and leaves the one-time backup safe. A later manager reload failure restores the original Bongo scanner documents as a second transaction rather than leaving a verified external scanner half-enabled.

  • Source: commit 20490970b11c5df9ba9687faf62fc59de06b3a61.
  • Package: mail-mta/bongo-9999::bongo, Gentoo debug installation.
  • Compiler: GCC 15.3.0 (Gentoo Hardened 15.3.0 p8), x86-64.
  • Live file SHA-256: ClamAV d5cc4f2b66d10f63b879ad54cb92b94fe43159c0be0f81e1f4581f5dd909ca82; SpamAssassin 15d5b5f4a02bb3f8b1a89c3229ac7c17c8c2a85ae5a68636272d2dadc9f2dff6.
  • Target: Linux 7.1.3-xanmod1-dist, 2026-07-22.
  • Result: 26 of 26 scanner transaction and CLI tests passed.

Runtime configuration: the successful scanner configuration from CFG-04 was inspected read-only; failure and rollback cases used temporary filesystem and service-manager fixtures.

CFG-08

Result: PASS

All Web deployment choices were exercised through the shared configuration model. Apache, nginx, and Nginx Proxy Manager select the same loopback-only HTTP boundary, preserve the configured public HTTPS URL, trust only the explicit proxy networks, and do not load a private key in the Web process. Direct HTTP binds the selected host address, clears proxy trust, remains an explicitly warned development choice, and is not rejected as malformed. Direct HTTPS selects ports 443 and 80, requires both certificate files, and rejects an incomplete pair. The complete 27-case configuration model passed.

The installed direct HTTP agent was then read over http://172.16.11.190:8080/. It returned 200, the expected CSP and Cache-Control: no-store, and a 19,643-byte login application. An isolated copy of the same installed agent used a disposable 3072-bit GnuTLS test key and leaf certificate on 127.0.0.1:18443. Forced TLS 1.2 and forced TLS 1.3 both returned the identical application bytes and security headers. Plain HTTP sent to that TLS listener was reset, and a separately generated private key failed before activation with X509: KEY_VALUES_MISMATCH. The temporary service-account substitution was needed only to run the installed root-to- bongo entry point as an unprivileged isolated process; the real privilege transition is tested by CFG-13.

The loopback-only HAProxy 3.3.5 fixture validated successfully and previously carried real PROXY v2 sessions through SMTP, submission, submissions, IMAP, IMAPS, POP3, POP3S, and ManageSieve. Greetings, TLS 1.3 handshakes, and the configured authentication paths passed. A forged PROXY header from an untrusted peer was handled as protocol input rather than accepted client metadata. Afterward, all four native agent documents were restored with PROXY protocol disabled. Mail TLS remained end-to-end passthrough; only the Web reverse-proxy modes terminate HTTP TLS.

Focused CTest repeated the common PROXY parser, SMTP PROXY handling, configuration model, and complete Web/DAV suite with loopback sockets enabled: four of four tests passed in 7.45 seconds. The Web/DAV executable covered 118 Python cases. A sandboxed attempt which prohibited socket() was discarded as an infrastructure failure and the same unchanged binaries passed outside that network restriction.

  • Source: commit 4b80136463a1105f53c3e39487f66f6cd13b1153 plus later documentation-only commits.
  • Package: mail-mta/bongo-9999::bongo, Gentoo debug installation.
  • Compiler: GCC 15.3.0 (Gentoo Hardened 15.3.0 p8), x86-64.
  • Installed Web executable SHA-256: 780a8b9418694611f8c4eacf6f2dfaf2bba5fd0f5ff1a1288c1d97acb215ae19.
  • Live Web document SHA-256: 37519ccdf668eb4e6ecf5914e47618e82578abe366665d03ec5dd9d3ffa1060f.
  • HAProxy fixture SHA-256: 21b66b1a101216d02cb6292395fdfb60d95b7e58c429b1db583b008518cf3573.
  • Direct HTTP, TLS 1.2, and TLS 1.3 response-body SHA-256: 56bdd094bc84936bbd3c22ecdf1d46817a674a95c98329dccc45a093700df5a1.
  • Target: Linux 7.1.3-xanmod1-dist, 2026-07-22.

Runtime configuration: the live service remained in its original direct HTTP test mode and active after the test. Direct HTTPS used only loopback, temporary state, and disposable key material below /tmp; the listener was stopped and no live Store document, certificate, or service state was changed.

CFG-09

Result: PASS

The real bongo-config crypto C/GnuTLS path was built with configuration, state, and runtime roots below /tmp and run as root in a private user namespace. It generated a self-signed X.509 v3 certificate and matching private key. The certificate uses a 3072-bit RSA key, RSA-SHA256 signature, random 128-bit positive serial, CA=false, digital-signature and key-encipherment usage, and the TLS Web Server extended-key purpose. Its subject and issuer are identical. Both configured DNS names, mail.bongo.test and smtp.bongo.test, are present as SANs.

The first run exposed a real multi-name defect: the deprecated three-argument GnuTLS setter replaced the SAN extension on every call, leaving only the last name. Commit 6e03d3a65d5d5d91601503dea7ade35c0bb19dd3 uses the current setter with explicit set/append semantics and adds a regression test which exports and re-imports the certificate before verifying every SAN.

Inside the namespace the TLS directory, public certificate, and private key were respectively owned by the configured root service identity with modes 0750, 0644, and 0640. The certificate and private-key Public Key ID was b4294a18ec7cb0be9664cb2e26a222b1a3c48b2d995bedfcecbcee1684ee6d97. A second generator invocation reported reuse, and both SHA-256 values remained byte-identical:

  • Certificate: 700431f87b9a41b8cb63f9a1640f2aad82e955b1c71860f0725fa83cfbda935c.
  • Private key: 6e2808e7229b0e2c91bd1e288b8aab79077dda1932126239a6142c7e74107bd1.

The focused SAN/configuration tests passed two of two. A complete rebuilt CTest run passed all 82 tests in 7.01 seconds.

Runtime configuration: isolated build and disposable TLS/state roots below /tmp; no live certificate, Store document, listener, or service state was changed. The private key was not committed.

CFG-10

Result: PASS

The repeatable contrib/testing/test-config-tls-material.sh integration test ran the real bongo-config crypto executable with compile-time TLS paths below /tmp. It first confirmed that a matching certificate/key pair covering all requested names is reused. It then independently injected a mismatched private key, an incomplete pair, a world-writable private key, private-key and certificate symlinks, malformed certificate data, and a requested DNS name which the otherwise valid certificate did not cover.

All seven unsafe or invalid states returned the documented crypto failure status and a specific diagnostic. SHA-256 snapshots before and after every validation failure were identical, including the missing-file state of the incomplete-pair case: validation never replaced, truncated, or removed an operator-supplied input. The script also rejects test directories outside /tmp and refuses any pre-existing TLS input before it starts.

  • Source under test: commit 6e03d3a65d5d5d91601503dea7ade35c0bb19dd3.
  • Result: valid-pair reuse plus seven rejection cases passed.
  • Regression coverage: multiple SANs, key/certificate identity, X.509 properties, file modes, byte-identical reuse, pair integrity, symlink and permission safety, malformed PEM, and hostname coverage.

Runtime configuration: private user namespace and disposable paths below /tmp. The harness removed all generated private-key material on exit and did not read or change the live Bongo TLS pair.

CFG-11

Result: PASS

Mail-DNS discovery was exercised for SPF, DKIM, and DMARC TXT records, including unrelated TXT filtering, missing records, multiple invalid SPF records, obsolete DMARC pct, DNS lookup failures, and the already-correct case. An already-correct SPF/DKIM/DMARC set produces neither an action nor an administrator notification. Outstanding work produces explicit record name, type, value, and reason fields.

contrib/testing/dkim-material-check.py generated a real 2048-bit RSA key with opendkim-genkey, imported it through Bongo's GnuTLS certtool validation, and compared the derived SubjectPublicKeyInfo value with OpenDKIM's published p= value. Bongo copied the key byte-for-byte with mode 0640, wrote the matching chunked DNS TXT hint, and reused the same material without creating an action when the matching key was reported as published. Separate regressions reject a symlink, a group-writable key, a non-RSA key, and any key below RSA-2048 before it can be installed.

Task creation was run twice against a real temporary SQLite task database. Exactly one per-user mail-dns task remained; it was open, warning severity, dismissible, and contained the complete SPF, DKIM, and DMARC action model. The task directory and database used modes 0750 and 0600. No database is created when no DNS work remains.

Finally, contrib/testing/mail-dns-live-check.py logged in to the installed test server through the real Web session API and found exactly one actionable task for bongo.test. It then logged in to the administrator mailbox through IMAPS, selected INBOX, searched by X-Bongo-Notification: mail-dns, and read the setup-generated message. The message was addressed to the administrator, contained forwardable SPF/DKIM/DMARC guidance, and contained no PEM private key block. The private DKIM key never left the server-side security-material path.

  • Source: commits 7f1bbf85, 3db4e725, and b2df8739.
  • Focused security-material result: 9 of 9 tests passed.
  • Complete rebuilt CTest result: 82 of 82 tests passed in 6.68 seconds.
  • Live result: actionable Web task and administrator IMAPS notification passed.

Runtime configuration: the DKIM import used disposable material below /tmp. The live Web/IMAPS check was read-only and left the active Bongo service, configuration, task state, mailbox message, and key material unchanged.

CFG-12

Result: PASS

contrib/testing/manager-lifecycle-check.sh exercised the installed systemd service on the disposable host. A reload retained manager PID 1038340. After the active Queue process was killed with SIGKILL, the same manager reaped it and started replacement PID 1038497. A normal service restart replaced the manager with PID 1038523; a subsequent stop completed cleanly and a fresh start produced PID 1038594.

The final case killed manager PID 1038594 with SIGKILL, deliberately bypassing its PID-file cleanup. systemd removed the remaining control group and, after the configured five-second restart delay, Bongo accepted the stale historical PID file and started manager PID 1038694. The service was left active with all configured agents parented by that manager.

This run exposed a real shutdown defect in the Antispam and Antivirus agents: their private signal state was unrelated to the shared BongoAgent state observed by the Queue listener. Commit 89d66d92 routes both signal handlers through BongoAgentHandleSignal. Before the repair, the manager reported that the scanners stubbornly refused to die and forced SIGKILL after ten seconds; after reinstalling the fix, normal stops completed in about one second and the new journal interval contained no forced scanner kill or shutdown timeout.

BONGO_ALLOW_LIVE_MANAGER_TEST=1 BONGO_TEST_TIMEOUT=60 \
  ./contrib/testing/manager-lifecycle-check.sh
  • Source fix: commit 89d66d92.
  • Complete clean GCC CTest result before installation: 82 of 82 passed in 8.31 seconds.
  • CMake cache SHA-256: 63bb3326db97ebe4a4200ff2ed98d4ecf9179a17da8c9522d556cfe650df3b7b.
  • Configuration-set SHA-256: 0a8a085ace18d7e2c1f93b0ea9c61ed5f39ebacab930543c7b105e1ed6ef776b.
  • Final service state: active/running, manager PID 1038694, systemd result success.

Runtime configuration: the installed Gentoo live package and existing disposable Bongo configuration were used. The test intentionally interrupted the Queue and manager processes, restored the service automatically on every exit path, and left the service active.

CFG-13

Result: PASS

The live process tree was audited after installing commit cdbf9320 and restarting the systemd service. contrib/testing/agent-privilege-check.sh verified every UID, GID, supplementary-group, and capability tuple directly from /proc, as well as parentage below the manager and systemd's capability boundary.

All 13 configured agents were present beneath the manager: Store, Queue, Antispam, Antivirus, Rules, ManageSieve, Collector, Worker, SMTP receive, SMTP client, IMAP, POP3, and Web. With the documented Worker exception, every agent had real, effective, saved, and filesystem UID/GID 404 (bongo), no supplementary groups, and zero inherited, permitted, effective, and ambient capabilities. Antispam and Antivirus had previously retained real/saved root; the repair changes them to the same permanent drop used by the other non-privileged agents.

The manager and scheduled Worker were separately checked: their effective and filesystem UID was bongo, supplementary groups were empty, and inherited, effective, and ambient capabilities were zero while idle. They retain only a bounded permitted set for replacement of privileged listeners and the Worker's atomic ACME certificate deployment. The installed systemd unit reduced CapabilityBoundingSet to exactly CHOWN, DAC_OVERRIDE, FOWNER, SETGID, SETUID, and NET_BIND_SERVICE; the earlier full kernel capability boundary is no longer inherited.

BONGO_ALLOW_LIVE_PRIVILEGE_TEST=1 \
  ./contrib/testing/agent-privilege-check.sh
  • Source: commit cdbf9320.
  • Complete rebuilt CTest result: 82 of 82 passed in 7.18 seconds.
  • Live result: 13 of 13 configured agents passed; service remained active/running with systemd result success.

Runtime configuration: the installed Gentoo live package and existing disposable Bongo configuration were used. The check was read-only and did not alter process, configuration, mailbox, Queue, or credential state.

CFG-14

Result: PASS

The Gentoo live package was rebuilt and reinstalled after overlay commit 0ee4d1e1. The ebuild now passes the versioned Gentoo documentation path to CMake, so the installed documentation lives below /usr/share/doc/bongo-9999; the former unversioned /usr/share/doc/bongo staging path and its QA notice are gone. The installed package contains 1,436 paths, none below /run or /var/run, and no runtime PID file.

contrib/testing/runtime-path-check.sh then stopped Bongo cleanly, removed only the guarded volatile /run/bongo directory, and invoked the installed bongo.conf tmpfiles declaration. It recreated /run/bongo, the persistent state roots, and the TLS directory with the declared ownership and modes:

750 bongo:bongo /run/bongo
750 bongo:bongo /var/lib/bongo
750 bongo:bongo /var/lib/bongo/dbf
700 bongo:bongo /var/lib/bongo/dbf/cookies
750 root:bongo /etc/bongo/ssl.d

After recreation the service started normally, placed its manager PID file below /run/bongo, and remained active/running as manager PID 1054117 with systemd result success.

BONGO_ALLOW_LIVE_RUNTIME_TEST=1 \
  ./contrib/testing/runtime-path-check.sh
  • Gentoo packaging source: overlay commit 0ee4d1e1.
  • Complete rebuilt CTest result: 82 of 82 tests passed in 6.38 seconds.
  • Live result: package-image, tmpfiles declaration, directory recreation, ownership/mode, PID placement, and service recovery checks all passed.

Runtime configuration: the installed Gentoo live package and existing disposable Bongo configuration were used. The test intentionally removed only the volatile /run/bongo tree while the service was stopped, recreated it through systemd-tmpfiles, and left the service active. Persistent mail, configuration, Queue, credential, and certificate contents were not removed or modified.

CFG-15

Result: PASS

Commit d4e4c0b1 tightened the generated systemd service while retaining the manager's bounded listener-recovery and Worker ACME deployment model. State and configuration mounts plus systemd-tmpfiles-setup.service are ordered before startup. ProtectSystem=strict now has an explicit, minimal write set for /var/lib/bongo, /run/bongo, /etc/bongo/ssl.d, and synchronized configuration. NoNewPrivileges, kernel/control-group/device/hostname protections, native syscall architecture, realtime and SUID/SGID restrictions, and the AF_INET/AF_INET6/AF_UNIX address-family allowlist are active.

The installed unit set passed systemd-analyze verify. The main unit's systemd-analyze security exposure score improved from 6.8 (MEDIUM) to 4.8 (OK). A real restart under that sandbox produced manager PID 1064443 and all 13 configured agents; the complete CFG-13 privilege audit passed again, with Worker PID 1064472 operating as a direct manager child.

The hourly SpamAssassin extra-channel timer was enabled and active. Its latest trigger completed with service result success and exit status zero, and its next randomized hourly trigger was scheduled. The live Worker configuration contained the registered acme-renew, scanner-health, and tlsrpt-delivery jobs. Its persistent scheduler directory and SQLite database were respectively 0750 bongo:bongo and 0600 bongo:bongo. The current service invocation also contained actual scheduled scanner-health activity, not merely a configured idle Worker.

BONGO_REQUIRE_WORKER_ACTIVITY=1 \
  ./contrib/testing/systemd-runtime-check.sh
  • Source: commit d4e4c0b1.
  • Complete rebuilt CTest result: 82 of 82 tests passed in 6.30 seconds.
  • Live result: installed-unit verification, mount ordering, effective sandbox properties, scanner timer, last updater result, Worker registry, scheduler persistence, and current scheduled activity all passed.
  • Final service state: active/running with systemd result success.

Runtime configuration: the installed Gentoo live package and existing disposable Bongo configuration were used. Bongo was restarted once to apply the installed unit. The scanner updater was not forced; its existing successful timer result was inspected. No mail, Queue, account, task, credential, rule, or certificate data was modified by the CFG-15 check.

CFG-16

Result: PASS

Commit 679a11ce made timezone-cache replacement atomic and made bongo-config tzcache return a nonzero status when rebuilding fails. The implementation now rejects an absent or empty snapshot, checks every opened zone and output stream, closes the snapshot directory, applies the final mode before publication, and renames the completed temporary cache over the old one only after all 597 zones have been converted. A failed rebuild therefore leaves the previous valid cache available.

The checked-in and freshly installed snapshots both identified IANA release 2026c. All 597 installed .zone files were non-empty and byte-identical to their source-tree counterparts. The normal CMake build did not run the developer-only update-zoneinfo target and performed no timezone download.

The new cal-timezone-cache-rebuild test built a cache from the checked-in snapshot in a temporary directory, loaded /bongo/UTC, /bongo/Europe/Vienna, and /bongo/America/New_York, then attempted a rebuild from an empty snapshot and verified that the preceding valid cache remained. The complete rebuilt suite passed 83 of 83 tests in 9.99 seconds.

After reinstalling the Gentoo live package from commit 679a11ce, the repeatable live check rebuilt /var/lib/bongo/dbf/bongo-tz.cache through the installed bongo-config. Publication changed the cache inode and produced a 25,125,625-byte file with mode and ownership 0644 bongo:bongo. Bongo stayed active throughout.

BONGO_TEST_SOURCE_ZONEINFO=/home/dbp/bongo-server/zoneinfo \
  ./contrib/testing/timezone-cache-check.sh

Runtime configuration: the installed Gentoo live package and existing disposable Bongo configuration were used. The timezone cache was atomically replaced; service, mail, Queue, account, task, credential, rule, and certificate state were not modified.

STQ-01

Result: PASS

Commit 6d1f657b centralised the new-account collection layout and added stable Sent, Trash, and Junk collections. Drafts, Archive, Sent, Trash, and Junk carry their corresponding IMAP SPECIAL-USE roles. Store creation now checks every collection insertion instead of silently accepting a partial account layout. The new store-initial-layout test verifies unique paths and GUIDs, parent-before-child ordering, all mail roles, the personal calendar, and the personal and collected address books. The complete rebuilt suite passed 84 of 84 tests in 10.68 seconds.

After installing the Gentoo live package and restarting the already-running test service, the repeatable live check created fresh users stq01c and stq01d. Each account received INBOX, Drafts, Archive, Sent, Trash, and Junk, plus its own calendar and address-book collections. Their Store databases were separate 131072-byte files with mode and ownership 0600 bongo:bongo; their distinct inode numbers were 863845572 and 863845713.

An authenticated STARTTLS IMAP session against the real port 143 listener then requested LIST "" "*" RETURN (SPECIAL-USE). It returned the expected roles from the live Store:

* LIST () "/" "INBOX"
* LIST (\Archive) "/" "archives"
* LIST (\Drafts) "/" "drafts"
* LIST (\Junk) "/" "junk"
* LIST (\Sent) "/" "sent"
* LIST (\Trash) "/" "trash"
BONGO_ALLOW_LIVE_USER_TEST=1 \
  BONGO_TEST_PASSWORD='<disposable-password>' \
  BONGO_TEST_USERS='stq01c stq01d' \
  BONGO_TEST_LAYOUT_USERS='stq01c stq01d' \
  ./contrib/testing/store-user-layout-check.sh

Runtime configuration: the installed Gentoo package and disposable local Bongo configuration were used. Clearly named test accounts and their empty standard collections were intentionally retained for later Store, Queue, quota, and protocol rows. No external mail was sent. The service remained active/running as manager PID 1182382 with systemd result success.

STQ-02

Result: PASS

Commit febe35c3 added binary-safe Queue message retrieval, explicit diagnostic target selection, direct local recovery delivery, Queue deletion, and binary Store export to the maintained administration clients. Unit tests cover target bounds, declared-length binary reads, malformed sizes, QADDM, and deletion. The complete rebuilt suite passed 84 of 84 tests in 10.81 seconds.

The same commit was pushed to master, installed as mail-mta/bongo-9999::bongo with GCC 15.3.0, and used by the live test on 2026-07-23. The fixture created target-999 entry 999-a61b246, retrieved its exact Queue-owned message, and delivered it through Queue's QADDM local Store path to stqqueue INBOX document 0000000000000013. The comparison includes the intentional Queue-generated Received trace header.

Both sides contained exactly 533 bytes and produced the same digest:

Queue SHA-256  0f6e37cbeef09d41eb62517fe34489c35188f42bde3b761912174f47bdcf3a9e
Store SHA-256  0f6e37cbeef09d41eb62517fe34489c35188f42bde3b761912174f47bdcf3a9e
./contrib/testing/queue-store-byte-check.sh

The test always deletes its held target-999 Queue entry; the delivered Store object remains as release evidence. The service finished active/running as manager PID 1196959 with systemd result success. The installed suffixless configuration and aliases readable to the test runner had aggregate fingerprint 2bd12226858159f3d6565c2368210b6e57a916257e0943317efa3f34bedfe5cc. No external mail, SMTP relay, collector source, or LMTP endpoint was used.

STQ-03

Result: PASS

Commit 78c25930 centralised the Queue free-space calculation in BongoQueueAvailableBytes() and made both the monitor and QDSPC require free space to be strictly greater than the configured reserve. The test suite covers values above 32 bits, the exact-reserve boundary, values below the reserve, and arithmetic at UINT64_MAX. The 32-bit helper was also compiled and run with -m32. The complete rebuilt suite passed 85 of 85 tests in 10.49 seconds.

The commit was pushed to master, installed as mail-mta/bongo-9999::bongo with GCC 15.3.0, and exercised against the live Queue on 2026-07-23:

./contrib/testing/queue-disk-space-check.sh
STQ-03 PASS free-before=65388068864 free-after=65388068864 reserve=5242880 reported=65382825984 block=4096

The reported value is exactly 5 MiB below the bracketed filesystem free-space measurements and therefore within the permitted one-block tolerance. This also proves that the live protocol and administration client preserve the value above UINT32_MAX. Bongo remained active/running as manager PID 1206471 with systemd result success. No Queue entry, Store object, external mail, SMTP relay, collector source, or LMTP endpoint was created or used by this test.

STQ-04

Result: PASS

Commit 4bcc8b64 made Queue control-file replacement atomic, rejects failed submission flushes and final renames, discards only the incomplete new entry, and retains the previous control file when a same-directory work-file commit fails. The /dev/full regression test proves that a failed flush cannot replace the original. The complete rebuilt suite passed 86 of 86 tests in 14.92 seconds. Commit ffd0e4d4 completed the isolated live fixture by using the recovery-supported Queue 009 class and guaranteeing closure of the unlinked tmpfs fill descriptor before cleanup.

The commits were pushed to master, installed as mail-mta/bongo-9999::bongo with GCC 15.3.0, and exercised on 2026-07-23:

./contrib/testing/queue-failure-safety-check.sh

The script mounted an 8 MiB tmpfs over the disposable Queue spool, retained a message in Queue 009, and consumed blocks through an open, unlinked file until QDSPC reported zero usable bytes. A second submission was rejected with 5221 Free disk space too low; the retained message was still readable and unchanged. It then overlaid the spool with a mode-000 directory. QRETR deferred with 4224 Can't read queue data; after removing the overlay, the same bytes and digest were available again:

STQ-04 PASS queue=009-a61c3b1 sha256=6aa2197e882af468a1bc3d193a5ddaf8aa026407cebcd22ffc0699de6f48060a full-reported=0 tmpfs-bytes=4096

The trap removed both mounts and restarted the original service. The spool was no longer a mount point, the operative reserve remained 5242880 bytes, and its post-test live measurement was:

free-before=65385586688 free-after=65385586688 reserve=5242880 reported=65380343808 block=4096

Bongo finished active/running as manager PID 1225547 with systemd result success. The temporary fixture, fill allocation, and failed submission were removed; no Store object, external mail, SMTP relay, collector source, or LMTP endpoint was used.

STQ-05

Result: PASS

Commit efc5173d added deterministic Queue listing, hold/release controls, the reserved Queue 999 class, and recovery of held entries across manager restarts. It also fixed QMOVE to use its parsed destination. Commit 69ab7094 added complete remote-delivery fixtures and deterministic expiry diagnostics. Commit 1441ab1a fixed the expired-recipient envelope boundary so the generated delivery-status recipient and enhanced status code are parsed correctly instead of falling back to a generic internal error. Unit tests cover the Queue protocol clients, movement, listing, recovery, expiry, and exact bounce-recipient formatting. The complete rebuilt suite passed 86 of 86 tests in 11.26 seconds.

The commits were pushed to master, installed as mail-mta/bongo-9999::bongo with GCC 15.3.0, and exercised on 2026-07-23:

./contrib/testing/queue-lifecycle-check.sh

The repeatable live test first listed a Queue 009 entry, moved it to hold, restarted Bongo, and proved that Queue 999 recovery retained it. It released the message to Queue 009, listed it there, deleted it, and confirmed that it was gone. A remote-delivery fixture for nobody@retry.invalid remained in Queue 007 after a flush with identical message bytes:

retry SHA-256  39b785579f9bdc5914216aa84f83cd19ca6014eef95d49e388b1d52f209f26a6

A separate held remote fixture was then expired without racing the normal remote worker. It left the Queue and created exactly one new Store object, 000000000000001b, in the isolated stqqueue inbox. The multipart delivery status notification contained:

Subject: Returned mail: Delivery time exceeded
Original-recipient: rfc822;nobody@retry.invalid
Final-recipient: rfc822;nobody@retry.invalid
Action: failed
Status: 5.4.7

The script reported:

STQ-05 PASS management=hold/restart/release/delete retry-sha256=39b785579f9bdc5914216aa84f83cd19ca6014eef95d49e388b1d52f209f26a6 dsn=000000000000001b status=5.4.7

All temporary Queue entries were removed. The intentionally retained DSN is local release evidence; no external mail, SMTP relay, collector source, or LMTP endpoint was used. Bongo finished active/running as manager PID 1253396 with systemd result success.

STQ-06

Result: PASS

Commit 6ab16588 added an installed Store concurrency diagnostic and its systemd coordinator. The diagnostic creates deterministic messages in Queue 999 and records the SHA-256 digest of every Queue-owned message. Separate threads then deliver through QADDM, read message bodies, move selected objects, and delete selected objects. The coordinator restarts the real Bongo service after the first eight deliveries while the Store threads remain active; the remaining 16 held Queue entries must survive and deliver after reconnection.

The complete rebuilt suite passed 86 of 86 tests in 11.41 seconds. The storetool test group also covers the fixture marker and the deterministic move/delete policy. The commit was pushed to master, installed as mail-mta/bongo-9999::bongo with GCC 15.3.0, and exercised twice on 2026-07-23. The clean evidence run was:

./contrib/testing/queue-store-concurrency-check.sh
STQ-06 PASS delivered=24 reads=22 moves=10 deletes=5 transient-reconnects=445 restart=1

The five messages numbered as deletion targets were absent. Each of the other 19 messages existed exactly once, in INBOX or /mail/STQ06 according to the test policy, and matched its pre-delivery Queue digest. Ten messages were moved successfully. The reader observed 22 distinct messages, including short-lived objects before concurrent deletion, without a content mismatch. The reported transient reconnect attempts occurred only while the deliberate service restart made the Store unavailable; every worker recovered.

The diagnostic removed all 24 test messages and every held Queue entry. Post-test listings of Queue, stq06 INBOX, and /mail/STQ06 were empty. No external mail, SMTP relay, collector source, or LMTP endpoint was used. Bongo finished active/running as manager PID 1264348 with systemd result success.

STQ-07

Result: PASS

The live round trip used separate disposable stq07src and stq07dst accounts. The source contained two RFC 5322 messages (UTF-8 and multipart), two vCards, and two iCalendar events linked to a non-default STQ07 calendar. The first mail had Seen|Flagged plus a custom property.

The implementation/repair pass found and fixed three independent defects:

  • commit 034656d0 made calendar event listing read document bodies and made LINKS return the Store client's normal list format;
  • commit 60ce9cd3 stopped restore from writing generated Store properties;
  • commit 2d27c7da implemented the existing Python client's I<imapuid> WRITE option and safely advances the collection UID counter;
  • commit f051f4ac preserves collection and SPECIAL-USE flags through CREATE.

Each repair passed all 86 CTest tests. The final commits were pushed to master, installed as mail-mta/bongo-9999::bongo with GCC 15.3.0, and exercised on 2026-07-23:

bongo-storetool -u stq07src store-backup /tmp/stq07src.backup
bongo-storetool -u stq07dst store-restore /tmp/stq07src.backup
bongo-storetool -u stq07dst store-backup /tmp/stq07dst.backup
./contrib/testing/store-backup-compare.py \
  /tmp/stq07src.backup /tmp/stq07dst.backup

The two archives contained the same 22 members. All six document payloads were byte-identical. Paths, GUIDs, document and collection flags, IMAP UIDs, mail properties, the custom test property, and both event-to-calendar links were identical. Only Store-generated creation/modification timestamps are excluded from the reusable comparison. No external mail, relay, collector source, or LMTP endpoint was used. Bongo remained active after the test.

WEB-09

Result: PASS

The implementation/repair pass found four independent live Store integration defects in the Web calendar list:

  • commit 713fd087 stopped relying on optional EVENTS properties and reads each event document by its Store UID;
  • commit ad0de11e drains the terminating EVENTS response before sending a READ command on the same NMAP stream;
  • commit d56dd63b decodes Store document bytes at the Python/native calendar boundary;
  • commit c9095f7b normalizes Store event paths before validating the public .ics resource name.

Each repair passed the focused Python regression tests and all 87 CTest tests. The final commit was pushed to master, installed as mail-mta/bongo-9999::bongo, and exercised on tiulk with GCC 15.3.0 on 2026-07-23. The suffixless files in /etc/bongo/config.d had the aggregate SHA-256 checksum:

0a8a085ace18d7e2c1f93b0ea9c61ed5f39ebacab930543c7b105e1ed6ef776b

A deterministic one-event ICS file was imported into the existing personal calendar. The Web API returned the event with UID bongo-web-live-file-import-20260723, summary Bongo ICS live import, the exact 2026-08-01 08:0009:00 UTC range, and the fixture description. This also reproduced and repaired the Python 3/NMAP failures that the native bongo-storetool calendar-events personal listing did not trigger.

The named holidays-at calendar was then created by subscribing through the Web API to the public HTTPS source:

https://www.feiertage-oesterreich.at/content/kalender-download/ics/feiertage-oesterreich.ics

The import response was:

{"calendar":"holidays-at","events":197,"subscribed":true}

A subsequent API list returned all 197 events and retained both subscribed: true and the canonical HTTPS source URL. The first returned events included Neujahr (§) and Heilige Drei Könige (§) with their original UIDs and all-day dates.

Finally, authenticated CalDAV discovery used a depth-one PROPFIND on /calendars/test1/. Bongo returned 207 Multi-Status and advertised all three expected resources:

/calendars/test1/
/calendars/test1/personal/
/calendars/test1/holidays-at/

The fetch implementation's automated coverage additionally rejects plaintext HTTP, loopback/private/link-local source addresses, oversized responses, redirect loops, non-calendar content, and invalid target names. The live request remained bounded by the configured redirect, response-size, and network timeouts. Bongo remained active after the test.

STQ-08

Result: PASS

The source audit found that four Store maintenance/debug commands did not enforce their intended privilege boundary. An authenticated user could select another account's Store (needed by the normal shared-resource ACL model) and then invoke REPAIR or the destructive RESET without an object-level ACL check. SHUTDOWN terminated the Store process without any authentication, and REINDEX was likewise unrestricted. Commit dc288d9a now requires a manager connection before REINDEX, REPAIR, RESET, or SHUTDOWN.

The same audit found that an invalid non-path document GUID caused ParseDocument() to ignore ParseGUID()'s failure. The server consequently wrote both a 3011 syntax response and a second lookup response for one command, leaving the next client command out of sync. The parser now returns the first failure immediately.

The complete rebuilt suite passed all 87 CTest tests in 11.65 seconds. The commit was pushed to master, installed as mail-mta/bongo-9999::bongo with GCC 15.3.0, and exercised on tiulk on 2026-07-23 with the reusable test:

export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/store-protocol-safety-check.py

The live test proved all of the following:

  • an unknown command returned 3000, pre-authentication Store selection returned 3241, and access without a selected Store returned 3243;
  • missing, invalid-GUID, and excessive READ arguments returned exactly one 3010 or 3011 response each, with a successful NOOP after the errors;
  • authenticated test1 could select test2 for the shared-store model but LIST /mail returned 4240, disclosing no foreign Store contents;
  • REINDEX, REPAIR, RESET, and SHUTDOWN each returned manager-only code 3243 to the normal user, and the same connection remained usable after every rejection;
  • a 4096-byte line closed only its offending client connection; a fresh connection immediately received the normal Store greeting and accepted NOOP.

The final clean run reported:

STQ-08 PASS checks=13 oversized-bytes=4096 manager-only=REINDEX,REPAIR,RESET,SHUTDOWN foreign-store=test2
ActiveState=active
MainPID=1419864
NRestarts=0

The test is non-destructive, keeps credentials out of Git, and leaves both disposable user Stores intact. No mail, relay, collector, or external service was involved.

STQ-09

Result: PASS

The Store quota implementation was checked at all three enforcement layers. Only document type STORE_DOCTYPE_MAIL contributes to the logical usage total. The per-user Store database holds that total and the administrative limit, while BEFORE INSERT and BEFORE UPDATE OF size,type SQLite triggers perform the final check inside the committing transaction. The earlier in-process checks provide prompt protocol errors, but are not relied upon for atomicity.

Commit de8d8aed extended the Store quota test with two independent SQLite connections released simultaneously against a 100-byte quota. Each attempted a 60-byte mail insert. Exactly one transaction committed, one received the database quota exceeded constraint, and the final charged usage was exactly 60 bytes. That race passed 100 consecutive iterations in 0.64 seconds. The complete rebuilt suite subsequently passed all 87 CTest tests in 12.01 seconds.

Commit 41976d79 added the reusable live check:

export BONGO_ALLOW_LIVE_USER_TEST=1
export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/store-quota-concurrency-check.py

Against the installed service, the script first preserved stqquota's exact usage and limit, then temporarily set the limit to one 65536-byte message plus one byte. It stored contact and calendar objects whose payloads were each larger than the complete mail quota; both succeeded and the Store's charged mail usage remained unchanged.

Two already-authenticated Store connections were then released through a thread barrier. Both attempted an independent 65536-byte mail write to INBOX. Exactly one returned success and the other returned Store status 5220. Charged usage was exactly one message, never two. Deleting the accepted message released its complete charge.

The entire live check passed twice. Its final output and post-test state were:

STQ-09 PASS user=stqquota baseline=0 mail-bytes=65536 concurrent=1-accepted,1-store-5220 excluded=contact,calendar quota-restored=yes
User: stqquota
Used: 0 bytes
Quota: unlimited
ActiveState=active
MainPID=1419864
NRestarts=0

The script removes every mail, contact, and calendar fixture in a finally cleanup path, restores the original administrative limit, keeps the password out of process arguments, and refuses to run without explicit live-test opt-in. No external mail or network service was involved.

STQ-10

Result: PASS

The complete Store-5220 path was exercised separately for ordinary SMTP mail and for a message whose remote POP3/IMAP source has already been removed by Collector.

The SMTP run first exposed a deterministic 180-second delay after DATA. GnuTLS had already decrypted the SMTP terminator into its internal record buffer, but ConnTcpRead() polled the kernel socket before consulting gnutls_record_check_pending(). Commit 332521b3 consumes pending plaintext first and covers the boundary with the TLS peer regression test. The same run also found that the DSN used the local Store username instead of the SMTP envelope recipient. Commits 2be3a0a1 and f31214eb preserve and format the RFC 3461 envelope address, including an independently supplied ORCPT value.

The final authenticated SMTP transaction completed through QUIT in 0.401 seconds. The complete test, including observing the generated DSN and restoring the fixture account, completed in 4.675 seconds:

STQ-10 SMTP PASS sender=test1@bongo.test recipient=stqquota@bongo.test accepted=yes store-partial=no dsn=5.2.2 queued=no quota-restored=yes

Collector requires different failure semantics because Queue owns the sole durable copy after a configured after_import deletion. Commit 88182956 added a live fixture that creates such a transaction and verifies its bytes, flags, Store state, retry and cleanup. Commit 0f768de1 added a bounded administrative retry command.

The first live Collector run proved that the complete message and MSG_FLAG_COLLECTED_MESSAGE survived Store status 5220, but also exposed a second timeout: after retaining the local mailbox recipient, Queue continued into the outgoing SMTP agent and held the entry lock until that agent timed out. Commit 7f382d27 now moves a quota-blocked Collector message to queue 6 and returns immediately. It cannot enter remote SMTP, and the normal Queue monitor or an explicit retry can process it after space is available.

All 88 CTest tests passed against that final source in 14.90 seconds. The commit was pushed to master, installed as mail-mta/bongo-9999::bongo, and the live test then reported:

STQ-10 collector trace 0.126s: baseline documents=0 bytes=0
STQ-10 collector trace 0.186s: quota constrained
STQ-10 collector trace 0.284s: enqueued as 000-a62598a
STQ-10 collector trace 1.347s: candidate retained queue 006-a62598b
STQ-10 collector trace 2.656s: retained queue settled as 006-a62598b
STQ-10 collector trace 2.934s: quota released
STQ-10 collector trace 3.250s: retry 006-a62598b: exit=0 stdout='' stderr=''
STQ-10 collector trace 3.502s: delivered as Store document 0000000000000023
STQ-10 COLLECTOR PASS user=stqquota retained=006-a62598b bytes=34549 duplicate=no partial=no retry-delivered=yes quota-restored=yes elapsed=4.050s

Post-test checks showed an empty Queue, zero charged bytes, an unlimited restored quota, and bongo.service active/running with NRestarts=0. No message left the local test system.

STQ-11

Result: PASS

The native store-quota regression test exercises a schema-version-zero database containing existing mail and non-mail objects. Applying the 0.7 migration creates the quota table and atomic triggers, advances PRAGMA user_version to 1, retains the existing 60-byte mail charge, excludes the 1000-byte non-mail object, and enforces a subsequently configured limit. The same test lowers a limit below usage, removes it again, and verifies exact accounting beyond 32 bits with a 5,001,000,050-byte logical total.

The reusable store-quota-state-check.py adds the bounded live companion:

export BONGO_ALLOW_LIVE_USER_TEST=1
export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/store-quota-state-check.py

On the installed service it placed a 65,536-byte message in the unlimited stqquota Store, lowered the limit to 65,535 bytes, and received Store status 5220 for the next growth attempt without changing usage. Removing the limit allowed another 4,096-byte message. The administrator path retained the exact signed 64-bit maximum, 9223372036854775807, and rejected the next integer with its normal size diagnostic.

The test then set a 135,168-byte administrative limit, made a portable PAX backup at 69,632 bytes usage, deleted the two test messages, and restored the archive. Restore reconstructed exactly 69,632 charged bytes while retaining the target account's 135,168-byte limit. This is intentional: a user-provided portable archive cannot replace an administrator's quota; a complete server backup preserves the per-user database which owns that policy.

The focused native and Python backup tests passed. The complete 88-test CTest suite then passed in 11.31 seconds, and the live run reported:

STQ-11 PASS user=stqquota baseline=0 lowered=65535 unlimited=yes max-limit=9223372036854775807 oversized-rejected=yes backup-used=69632 backup-limit=135168 restore-usage=yes restore-limit=yes quota-restored=yes

The cleanup path restored the original PAX backup and original quota. Final checks showed zero charged bytes, an unlimited quota, and bongo.service active/running with NRestarts=0. No message left the local test system.

STQ-12

Result: PASS

Commits 92e0ba11 and b4f3a67a bound external collection by both a global pending-message count and a per-user count. Collector obtains the durable count from authenticated Queue command QCOUNT COLLECTED [user], increments its local view after every successful commit, and stops before fetching the next remote message when either configured limit is reached. External accounts are processed serially: one POP3 or IMAP account completes its bounded poll before Collector starts the next account.

The Queue counter accepts committed control files and in-progress replacement controls, deduplicates their queue IDs, requires the collected-message flag and matching local recipient, and now also requires the corresponding message data file. This last condition prevents an administrative deletion or completed delivery from leaving an orphaned work control that falsely holds Collector at its cap. QDELE also removes the corresponding work control.

The reusable live check uses the local Cyrus fixture and a disposable Bongo user:

export BONGO_ALLOW_LIVE_USER_TEST=1
export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/collector-flood-quota-check.py

It seeded eight distinct 128-KiB messages into a Cyrus POP3 account and eight into a Cyrus IMAP account. With stqquota limited to 400,000 bytes, exactly two messages reached Store and the remaining fourteen stayed durably in Queue 006. All sixteen unique markers were present exactly once, the charged usage never exceeded the configured quota, and both remote mailboxes were deleted only after the corresponding Queue commit.

The second phase temporarily set collector.maximum_pending_messages_per_user to one, seeded two more POP3 messages, and verified that Collector committed exactly one. It recorded the pending-message-limit diagnostic and left the first over-limit message at the provider. The successful installed-service run reported:

STQ-12 PASS pop3=8 imap=8 size=131072 quota-used=273887/400000 store=2 queue=14 duplicates=no overflow=no source-retained-at-limit=yes quota-restored=yes

The final GCC debug suite passed all 91 CTest tests in 11.48 seconds. The live-test cleanup removed its external-account records, remote fixtures, Store objects and Queue entries, restored the original Collector document and unlimited quota, and left bongo.service active. No message left the local test system.

SMTP-01

Result: PASS

The reusable smtp-basic-check.py drives port 25 directly rather than relying on a high-level SMTP client's implicit command ordering:

./contrib/testing/smtp-basic-check.py

It opened independent legacy SMTP and ESMTP sessions. Both received a non-empty 220 greeting. The HELO session returned a single 250 response without extensions; EHLO returned the configured multiline extension list and advertised HELP. Both sessions accepted NOOP with optional text, RSET and HELP, then returned 221 and closed the connection after QUIT.

The installed policy had smtp.allow_vrfy=false. EHLO therefore did not advertise VRFY. Explicit VRFY requests for the existing test1 account and a deliberately absent account both returned the same 252 response, preventing local-user enumeration. The live run reported:

SMTP-01 PASS host=127.0.0.1 port=25 greeting=yes helo-lines=1 ehlo-lines=11 noop=yes rset=yes help=yes vrfy=252-no-disclosure quit=yes sessions=2

The focused native smtp-capabilities and smtp-protocol tests also passed. The live test sends no envelope or message data and therefore leaves Store, Queue and external systems unchanged.

SMTP-02/03

Result: PASS

The reusable smtp-submission-auth-check.py exercises both authenticated submission listeners without relying on a high-level SMTP client's mechanism selection:

export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/smtp-submission-auth-check.py

On port 587 the first EHLO advertised STARTTLS but did not advertise AUTH. An explicit AUTH attempt containing no real credential was rejected with 538. After STARTTLS and the mandatory second EHLO, the server advertised exactly the supported GSASL password mechanisms, including PLAIN and LOGIN. Separate TLS sessions completed both mechanisms with the disposable test1 credential and rejected a deliberately wrong password with 535. A repeated STARTTLS request in an already encrypted session was rejected with 554.

Port 465 performed TLS before the SMTP greeting, did not advertise STARTTLS, and passed the same PLAIN, LOGIN, and invalid-password cases. Both listeners negotiated TLS 1.3 while the test's client-side minimum was TLS 1.2. The installed-service run reported:

SMTP-02/03 PASS host=127.0.0.1 submission=587/TLSv1.3 smtps=465/TLSv1.3 pre-tls-auth=538 auth=PLAIN,LOGIN invalid=535 repeated-starttls=554

The focused native sasl-password-mechanisms, smtp-capabilities, and smtp-protocol tests also passed. The live check authenticates only; it sends no envelope or message data and therefore leaves Store, Queue, and external systems unchanged.

SMTP-04

Result: PASS

The reusable smtp-internal-relay-check.py exercised the dedicated internal SMTP listener on 172.16.11.190:26:

export BONGO_ALLOW_LIVE_SMTP_TEST=1
./contrib/testing/smtp-internal-relay-check.py

A connection sourced from the configured 172.16.11.0/24 network received the normal greeting. The same destination reached from 127.0.0.1 received exactly 554 5.7.1 Source address not permitted\r\n and an immediate close. This caught and fixed a manual length of 41 for the 40-byte literal, which had placed a NUL byte on the SMTP wire.

The test then restarted the installed service with isolated temporary limits: one concurrent connection, one recipient per minute, 64 bytes per minute, and one message per minute. A second held connection and a second recipient were rejected with their specific 451 diagnostics. An oversized DATA body was rejected by the byte limit. For the message-count case, the first DATA transaction intentionally used an internationalized header without SMTPUTF8, causing a pre-commit 550; the next DATA transaction then proved that the one-message limit had been consumed and returned 451. Thus none of the limit probes could enter Queue or Store.

The installed-service run reported:

SMTP-04 PASS host=172.16.11.190:26 allowed=172.16.11.190 denied=127.0.0.1 network=554-exact connection-limit=451 recipient-limit=451 byte-limit=451 message-limit=451 queue-write=no restored=yes

The test restored the original SMTP JSON byte-for-byte and left bongo.service active. A source-wide literal-length audit also found and fixed bongo-sendmail truncating the final LF from dot-stuffed "..\r\n". The new c-literal-io-lengths CTest prevents NUL inclusion, truncation, and literal over-read regressions in Bongo's connection-write helpers. The final GCC debug suite passed all 92 CTest tests in 7.37 seconds.

SMTP-05

Result: PASS

Commits 14fbb55a, 90e30e99, and 4ac9cf49 separated the internal-relay identity and sender policy into a focused module, allowed trusted port-26 clients to address remote recipients without SMTP authentication, and added both native and installed-service regression tests.

The sender policy preserves an address already using the configured relay domain. A real subdomain is accepted and converted to a canonical plus-address: for example, root@media.bongo.test becomes root+media@bongo.test, while rsync@backup.bongo.test becomes rsync+backup@bongo.test. Local device defaults and unrelated domains are also canonicalized. A suffix-boundary check prevents a lookalike such as attackerbongo.test from being mistaken for a hosted subdomain. The null reverse path remains unchanged.

Device identity first uses the explicit source-IP mapping. The DNS fallback accepts only strict DNS labels below a configured suffix and requires forward-confirmed reverse DNS. Focused native coverage includes mapping precedence, suffix boundaries, invalid labels, forward-confirmation, truncation, sender normalization, and the authenticated-or-trusted relay decision.

The reusable live check temporarily selected an unreachable loopback relayhost and sent only to the reserved .invalid namespace:

export BONGO_ALLOW_LIVE_SMTP_TEST=1
./contrib/testing/smtp-internal-normalization-check.py

Each committed entry was identified by a unique message token, atomically moved to Queue 999 to avoid a delivery-worker race, inspected through the real Queue envelope API, and deleted. The ten cases covered local hostnames, the explicit device mapping, single and nested hosted subdomains, a send-only subdomain, the exact hosted domain, a suffix lookalike, an unrelated domain, and a null sender. The installed-service run reported:

SMTP-05 PASS host=172.16.11.190:26 source=172.16.11.190 device=matrix cases=10 queue-envelope=yes queue-held=yes fcrdns=unit-tested external-boundary=yes internet-delivery=no restored=yes

The SMTP configuration round-tripped exactly, no test Queue entry remained, and bongo.service was active after cleanup. The final GCC debug suite passed all 93 CTest tests in 12.16 seconds.

SMTP-06

Result: PASS

The reusable smtp-local-delivery-check.py submits a uniquely marked message from disposable account test1 to local account test2:

export BONGO_ALLOW_LIVE_USER_TEST=1
export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/smtp-local-delivery-check.py

The test requires STARTTLS on port 587, performs the second EHLO, confirms that AUTH is available only on the encrypted session, authenticates as the envelope sender, and submits to test2@bongo.test. It then consumes the streaming Store LIST response completely before reading objects, finds the unique marker in test2's real /mail/INBOX, and verifies the From, To, Message-ID, marker header, and body. More than one matching Store object is a hard failure.

The installed-service run reported:

SMTP-06 PASS host=127.0.0.1:587 tls=TLSv1.3 auth=test1 recipient=test2@bongo.test store-inbox=yes duplicate=no queue-clean=yes store-clean=yes

The cleanup path deleted the exact Store object, removed any matching Queue entry if a partial run left one, and verified that no marked object remained. No configuration changed and no message was routed outside the local Bongo instance.

SMTP-30

Result: PASS

The reusable smtp-client-interoperability-check.py submits distinct, uniquely marked messages with four independent installed clients:

  • curl's SMTP URL handler with required STARTTLS;
  • swaks with STARTTLS and AUTH LOGIN;
  • Xeams Email Sender with its STARTTLS mode;
  • GNU Mailutils mail with GSASL-enabled SMTP support.
export BONGO_ALLOW_LIVE_USER_TEST=1
export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/smtp-client-interoperability-check.py

Each client authenticated on port 587 as test1, delivered to test2@bongo.test, and produced exactly one independently verifiable Store object. The check consumed Store LIST before READ, verified message markers and bodies, and removed the exact Store and Queue fixtures before advancing to the next client. Password-bearing curl, swaks, and Mailutils configuration files were mode 0600 in an automatically removed temporary directory. Xeams' upstream command-line interface necessarily received its disposable test password as an argument.

The installed-service run reported:

SMTP-30 PASS host=127.0.0.1:587 clients=curl,swaks,xeams,mailutils recipient=test2@bongo.test store-inbox=yes duplicate=no queue-clean=yes store-clean=yes versions=curl 8.20.0; swaks version 20240103.0; mail (GNU Mailutils) 3.21

GNU Mailutils was built with its sasl USE flag so the direct client uses GSASL after STARTTLS. No client was permitted to relay without successful authentication, and no message left the local Bongo test domain.

The check was repeated after the local-maildrop hardening at installed source commit d954e423774d21485ebb9ba051c2947dc295c3bf, then expanded to cover the same four programs without authentication on the public port 25 and trusted port 26 listeners. A pseudo-terminal Telnet client was added to both plain listeners. It consumed each server response before typing the next command and waited one second after every reply, including after the greeting and message acceptance. All fourteen messages produced one delivery, no duplicates, and clean Store and Queue state:

SMTP-30 PASS submission=127.0.0.1:587 inbound=127.0.0.1:25 internal=172.16.11.190:26 deliveries=14 clients=submission-auth:curl,submission-auth:swaks,submission-auth:xeams,submission-auth:mailutils,inbound-noauth:curl,inbound-noauth:swaks,inbound-noauth:xeams,inbound-noauth:mailutils,inbound-noauth:telnet,internal-noauth:curl,internal-noauth:swaks,internal-noauth:xeams,internal-noauth:mailutils,internal-noauth:telnet recipient=test2@bongo.test store-inbox=yes duplicate=no queue-clean=yes store-clean=yes versions=curl 8.20.0; swaks version 20240103.0; mail (GNU Mailutils) 3.21

SMTP-31

Result: PASS

The reusable sendmail-local-submission-check.py runs as the unprivileged desktop account and submits two distinct messages through the installed sendmail compatibility interface:

  • /usr/sbin/sendmail -oi -t -f, with envelope recipients taken from the message;
  • GNU Mailutils mail, configured to use the same sendmail interface.
export BONGO_ALLOW_LIVE_USER_TEST=1
export BONGO_TEST_PASSWORD='<disposable-test-password>'
./contrib/testing/sendmail-local-submission-check.py

Both paths reached Bongo through the protected, group-writable /var/spool/bongo/maildrop handoff. The submitting process could not read the Bongo system credential. Each marker appeared exactly once in test2@bongo.test's Store INBOX, and the Bcc field used to exercise recipient extraction was absent from the stored message.

The installed-service run at source commit d954e423774d21485ebb9ba051c2947dc295c3bf reported:

SMTP-31 PASS user=1000 sendmail=/usr/sbin/sendmail clients=sendmail,GNU-mail master-credential=unreadable recipient=test2@bongo.test deliveries=2 duplicate=no bcc-removed=yes store-clean=yes

The test removed both exact Store objects and any matching Queue entries. The maildrop spool was empty afterward. No Internet recipient or external relay was used.

SMTP-32

Result: PASS

The SMTP listener previously read socket_timeout from the Store but started ConnIO with a fixed 600-second value. Source commit 95d4273fef2b3f6104bf68606dba783a738731e3 makes the ConnIO default a run-time setting, changes the fresh-install default to Postfix's normal 300 seconds, and rejects values outside 1 through 3600 seconds. The complete GCC debug build and all 96 CTests passed, including the new ConnIO default-timeout test and configuration-model bounds test.

The reusable smtp-telnet-timeout-check.py then changed the installed test instance to a three-second timeout. It opened a real Telnet client in a pseudo-terminal against both port 25 and trusted-device port 26. For each listener it first waited without sending a command. It then opened a second connection and waited two seconds after each server reply before typing EHLO, NOOP, and RSET. Those paced sessions lasted longer than three seconds in total, proving that activity resets the next-operation timer, then were deliberately abandoned.

export BONGO_ALLOW_LIVE_SMTP_TEST=1
./contrib/testing/smtp-telnet-timeout-check.py

The installed-service run reported:

SMTP-32 PASS configured-timeout=3s command-delay=2s sessions=inbound=idle:3.00s,paced-idle:3.00s;internal=idle:3.00s,paced-idle:3.00s paced-commands=EHLO,NOOP,RSET config-restored=yes service=active

All four abandoned sessions closed at the configured boundary. The original SMTP document was restored and its canonical bongo-admin __config-read smtp output had SHA-256 7666db995baf210638d92ae241f7bb10e0991efc7334d980bbb5fcd438f23925. bongo.service was active after the final restart.

SMTP-33

Result: PASS

Source commits 54eee9efaf4ec45ae3889a7ebaff3abe5c94b0df and 634040014fe3808e03e83e9b3c2730fce2299f5e add load-dependent SMTP timeouts and upgrade-safe defaults. Newly accepted sessions switch from the normal timeout to the short stress timeout when their projected connection count reaches the configured percentage of max_thread_load. The default is 10 seconds at 80 percent of 10,000 connections. Existing sessions retain the timeout selected when they were accepted.

The implementation applies before PROXY protocol and TLS processing on the public inbound, trusted-device, submission, and implicit-TLS listeners. The complete GCC debug build and all 97 CTests passed, including the load-policy boundary test and the per-connection ConnIO timeout test. The Python configuration suite also passed as part of configuration-model.

The reusable live check lowers the threshold to two connections and uses two simultaneous real sockets. The first session receives the normal five-second timeout. Accepting the second session reaches 100 percent load, so only that new session receives the two-second stress timeout.

export BONGO_ALLOW_LIVE_SMTP_TEST=1
./contrib/testing/smtp-stress-timeout-check.py

The installed-service run reported:

SMTP-33 PASS maximum-connections=2 stress-threshold=100% normal-timeout=5s stress-timeout=2s sessions=inbound=normal:5.01s,stress:2.00s;internal=normal:5.01s,stress:2.00s;submission=normal:5.00s,stress:2.00s config-restored=yes service=active

The check covered ports 25, 26, and 587. It restored the original SMTP document exactly; its canonical bongo-admin __config-read smtp output still had SHA-256 7666db995baf210638d92ae241f7bb10e0991efc7334d980bbb5fcd438f23925. The final service state was active and included a running bongosmtp process.

SMTP-07

Result: PASS

The first direct-MX fixture run exposed a production DNS bug before any test server received a connection. XplDns_Query() passed ns_c_any as the DNS class to res_query(). That constant means class 255; it does not mean that the resolver should return an Internet-class answer. Commit b602315ed9e4fa0e65c34bfc4cefa6ea6fe1b9a5 changes all XPL DNS mail-record queries to the required ns_c_in class. This fixes direct MX/A resolution and the TXT lookup path shared by mail policy features.

The reusable smtp-outbound-opportunistic-tls-check.py installs a temporary loopback DNS resolver and publishes three isolated MX routes:

  • a server which advertises STARTTLS and completes a TLS 1.2-or-newer handshake;
  • a server which does not advertise STARTTLS;
  • a server which advertises STARTTLS, accepts the command, then aborts the TLS handshake.
sudo ./contrib/testing/smtp-outbound-opportunistic-tls-check.py --live

To let the fixture own standard MX port 25, the check temporarily changes Bongo's public listener to port 10025 while leaving trusted submission on port 26 available. Each uniquely marked message is accepted through port 26 and then delivered by the real Queue and bongosmtpc direct-MX path. The failed handshake must close the unusable stream and cause exactly one new plaintext SMTP connection; reusing the failed stream or delivering twice is a hard failure.

The installed debug build at source commit b602315ed9e4fa0e65c34bfc4cefa6ea6fe1b9a5 reported:

SMTP-07 PASS starttls=tls/connections:1 plain=plaintext/connections:1 handshake-failure=plaintext-reconnect/connections:2 duplicates=no queue-clean=yes resolver-restored=yes config-restored=yes service-restored=active

The same source completed a clean GCC debug build and all 97 CTests. The live check removed its Queue fixtures, restored the original resolver bytes and SMTP configuration, and returned bongo.service to active state. No test recipient used public DNS or an Internet destination.

SMTP-08

Result: PASS

The reusable smtp-required-tls-check.py exercises the real trusted SMTP listener, Queue, direct-MX resolver, and bongosmtpc delivery agent in two phases. Global mandatory TLS delivers only to a TLS-capable MX. A plaintext MX and a peer which aborts after accepting STARTTLS remain queued without a plaintext fallback.

The second phase submits RFC 8689 REQUIRETLS messages over STARTTLS. Its valid peer presents a hostname-matching certificate chained to a temporary private test trust anchor and advertises REQUIRETLS after STARTTLS. Bongo delivers that message encrypted and includes REQUIRETLS on the outbound MAIL FROM. Peers which omit TLS or omit REQUIRETLS after TLS remain in Queue 7 and never receive MAIL FROM.

During this run, commits 43bc6d1e8724780d93c4986ec90f8b371c6c64ae and 43315642227fb7ed35526a1cf681eecabf12e00b were present. The first makes a newly registered SMTP delivery agent retry persisted outgoing entries immediately once, after which failures return to the normal retry interval. The second adds the optional outbound_tls_ca_file without replacing the system trust store. The related strict C build, two ConnIO TLS tests, nine Queue tests, and 32 Python configuration-model tests passed.

sudo ./contrib/testing/smtp-required-tls-check.py --live

The installed debug build reported:

SMTP-08 PASS global-required=encrypted/no-plaintext-fallback requiretls=advertised/propagated/deferred-on-unsupported queue-clean=yes resolver-restored=yes config-restored=yes service-restored=active

The fixture uses isolated loopback MX servers and a temporary trust file under Bongo's state directory so the hardened systemd service with PrivateTmp can read the certificate but not its private key. It deletes all uniquely marked test mail and restores the original resolver bytes, SMTP Store document, local configuration mirror, and active service state.