cutover-run.md step 4 says to write down what has to be true afterwards while the old server can still be asked, and step 10 checks against it. Done by hand it gets skipped, and skipping it turns "each mailbox holds what was recorded" into "each mailbox holds something", which is a different check and will not catch a partial copy. It reuses record-compat.py's client rather than growing a second one, so the guard that makes it safe to point at a live server — call() refuses any method that is not a /get or a /query — covers this too. Verified that it bites: x:Account/set is refused before anything is sent. From the administrator alone it records every account with its address, aliases, tenant and usedDiskQuota, which is the number that moves if mail goes missing, plus the domains and tenants. Exact per-mailbox counts need the mailbox's own credentials, since an administrator has reach over an account but not always into it, so --as takes one and repeats. For a handful of mailboxes that is worth it: it makes step 10 an equality rather than an estimate. Aliases are resolved to the domain's name rather than its id, because an id is not what anyone checks against at 2am.
Fork tooling
strip.py
Makes an Enterprise-free snapshot of an upstream release. See the docstring and docs/spec/SPEC.md §2.2 for what it does and why.
git clone https://github.com/stalwartlabs/stalwart.git ~/src/stalwart-upstream # outside this repo
git -C ~/src/stalwart-upstream fetch --tags
tools/fork/strip.py --upstream ~/src/stalwart-upstream --ref v0.16.22 --out /tmp/strip-v0.16.22
It writes OUT/tree (the stripped source) and OUT/STRIP-REPORT.md and
.json. Exit 0 means verified clean. Exit 1 means malformed markers, or
something Enterprise-only survived. Read the report's Problems section.
The report's Third-party code section lists upstream code under other
licenses. Files marked new need their notice added to THIRD-PARTY.md
at the repository root before the import is merged.
It needs Python 3.12+ (for tarfile's data filter) and git.
record-compat.py
Records what the *_compat tests compare against, from the Enterprise
server, while it is still running. Read-only: /get and /query only.
See docs/spec/compat-tests.md.
tools/fork/record-compat.py --server https://mail.example.org \
--admin '[email protected]:PASSWORD' --out ./compat \
--tenant-admin '[email protected]:PASSWORD'
run-compat.sh
Runs the *_compat tests against a copy of INBUXA's RocksDB store, making
a fresh copy for each one. See docs/spec/compat-tests.md.
tools/fork/run-compat.sh --store /srv/inbuxa-copy/rocks.db \
--admin '[email protected]:PASSWORD' --recordings ~/compat