Repository navigation
v4.0.2 — HealthChecks lockstep + JSON hardening + test guards
Patch-реліз без breaking changes. Якщо ти використовуєш SignalCli.NET.HealthChecks — онови його разом з main package: до 4.0.2 версії розійшлися й змішування пакетів давало runtime crash. Решта — 8 нових захисних тестів і одна реальна знахідка про JSON-валідацію, яка мовчки не fire'ила у продакшені.
🐛 Виправлено
-
Якщо консьюм'иш обидва пакети (
SignalCli.NET+SignalCli.NET.HealthChecks) — онови їх разом. До 4.0.2 main lib був4.0.1, а health-checks-adapter —3.0.0. Змішування пакетів кидалоMissingMethodExceptionна першому health-check probe (бо adapter читає internal'и main lib через[InternalsVisibleTo]). Тепер обидва завжди ходять в lockstep через єдиний MSBuild property уDirectory.Build.props. Bug-class виключено: reflection-тестVersionLockstepTestsловить розбіжність до merge'у. (NF-003, RG07) -
JSON duplicate-key захист (rule #18) тепер реально діє на production-шляху. З 4.0.0 ми оголошували що malformed signal-cli response з повтореним ключем fail'ить deserialize. У реальності — fail'ило тільки на reflection-шляху, а production деsеріалізує через source-gen fast-path який власний runtime-flag не консумує. Тепер захист увімкнено на обох рівнях (runtime flag + source-gen attribute). Без впливу на нормальні signal-cli responses — Jackson на upstream-стороні фізично не може емітити дублікати; fix чисто defensive проти MITM/corruption. Знайшли під час audit'у коли наш же RG-тест спочатку failed. (json-hardening-source-gen-attribute)
-
CI pipeline нарешті пушить
SignalCli.NET.HealthChecksна NuGet feed разом з main package. До 4.0.2publish-nuget.ymlworkflow мав pack-steps для 5 пакетів (SignalCli.NET,SignalCli.Runtime,SignalCli.Runtime.Native,SignalCli.Runtime.Jre.{win-x64,osx-arm64}) — алеSignalCli.NET.HealthChecksбув відсутній. Net effect: csproj-сторона мала версії в lockstep (NF-003 main fix), але consumer-сторона все одно отримувала stale3.0.0HealthChecks-пакета з registry бо нічого свіжіше не пушилось. Цей gap робив весь NF-003 lockstep косметичним на consumer-стороні. Тепер крок присутній — після першогоgh release create v4.0.2HealthChecks теж потрапить на feed. (nf003-completion follow-up)
🛡️ Захист від регресій
8 нових unit + 1 E2E-тести закривають declared-але-untested invariants з CLAUDE.md "Future development guardrails":
-
Паралельні JSON-RPC виклики тепер pinned проти реального signal-cli — не лише проти mock'а на unit-рівні. Новий E2E запускає bundled JRE, кидає 10 паралельних
version-викликів через справжній signal-cli virtual-thread dispatcher, асертить що всі 10 повертають свою власну відповідь. Якщо хтось у майбутньому замінитьConcurrentDictionary<id, TCS>наQueue<TCS>"бо порядок збережений" — unit-тести з in-orderSubject<T>-моком цього б не побачили; цей E2E одразу впаде. (e2e-coverage-expansion) -
Observability counters тепер pinned на всіх 3 тригерах перезапуску. Раніше privacy-guards перевіряли лише відсутність PII у Meter-tags, а фактичне інкрементування
signalcli.process.restarts{trigger=…}було pinned тільки наtrigger=force. Теперtrigger=crash(через event-raise на mock IProcess) іtrigger=health(черезFakeTimeProvider.AdvanceповзHealthCheckIntervalSeconds) теж покриті. (G4 subcases — T04, T05) -
Event-API симетрія enforced reflection-тестом. CLAUDE.md правило "кожен
IObservable<T>event-kind має парнийIAsyncEnumerable<T>метод" раніше enforcъ'вся code-review'ом. ТеперEventApiSymmetryTestsreflectively скануєISignalEventServiceі fail'ить build якщо хтось додав 11-й event без парного методу. (NF-002, RG06) -
JSON duplicate-key захист — 3-шаровий guard. Окрім самого fix'у з "Виправлено" вище, додано 3 facts у
JsonSerializationTests:SignalJsonOptions_…IsFalse,JsonDocumentOptions_…ThrowsOnDuplicateKey,SignalJsonContext_…ThrowsOnDuplicateKey. Видалення будь-якого з 3 шарів (runtime flag, .NET 10 API contract, source-gen attribute) surface'иться як failed test. (G12, RG05) -
JSON-RPC error wins over result. Захисний test пінує що при malformed-response (одночасно
resultІerror) JsonRpcClient кидає exception, а не повертає result. CHANGELOG [4.0.1] стверджував покриття;grepпоказав що тесту не існувало. Тепер дійсно існує. (NF-001, G9)
🛠 Інше
-
Test-проект тепер ловить warnings як errors (як main lib давно). Раніше тихо акумулювалися 3
xUnit1031violations уSyncDisposeDuringCleanupTests.cs(deadlock-prone.GetAwaiter().GetResult()). Виправлено: метод-сигнатуриasync Task+await;service.Dispose()навмисно залишається SYNC бо саме його тести й вимірюють. (NF-004) -
Microsoft.Extensions.*.Testingbumped 9.0.0 → 10.0.0 — закриває last mismatched-major у dependency graph. Public-surface unchanged per MS Learn. (NF-005) -
Версія обох NuGet-пакетів тепер централізована в
Directory.Build.props → <SignalCliPackageVersion>. Bump = single-file edit. Hardcoded<Version>у будь-якому csproj заборонено. -
CLAUDE.md розширено двома секціями для майбутніх контрибуторів + новим правилом:
- "Audit baseline" — мінімальна планка яку PR не може опустити (test counts, regression guards, архітектурні invariants).
- "How we discovered these issues" — 5 failure-mode-сценаріїв з PR-time checklists, щоб не повторювати ті самі паттерни.
- "Version-CHANGELOG lockstep" + "CHANGELOG voice template" — bump версії МУСИТЬ йти з CHANGELOG-секцією в одному коміті; новий template для consumer-first voice (bold leading claim, технічна обгортка, internal-IDs у дужках).
- Виправлено константа
MaxInlineEncodedAttachmentBytes: 15 000 000 → 12 000 000 (drift з 4.0.0 — реальне значення в коді змінилось уsignal-cli-protocol-alignment §5, doc відстав). (NF-006)
-
CHANGELOG voice tightened — починаючи з [4.0.2] (цей entry), пишемо у consumer-first voice. Старіші версії [4.0.1]/[4.0.0] перероблено в тому ж коміті задля консистенції.
📊 Тестова статистика
- Unit: 279 → 287 (+8 захисних тестів).
- Integration: 7 → 8 (+1 E2E на паралельний RPC).
- Build на src/ + Tests/: 0 warnings, 0 errors.
Pending follow-up
Нічого — усі audit v2.1 знахідки закриті.