chore: back-merge release v0.11.2 into develop#359
Merged
Conversation
## Summary Release v0.11.0 — ships seven bug fixes across the ENIP, DNP3, and Modbus analyzers (EC-X1/EC-X2 carry-buffer direction split and `saturating_sub` clock-backwards fix applied to all three protocols, plus the DNP3 desync-latch `frame_count == 0` guard). All fixes landed on `develop` via PRs #334 (ENIP), #335 (DNP3), and #336 (Modbus + DNP3 desync-latch). This PR is the gitflow release merge from `release/0.11.0` → `main`. --- ## What Changed ### Fixed — EC-X1 (per-direction carry buffer split) All three ICS analyzers previously used a **single shared carry buffer** for both TCP directions (client→server and server→client). A response packet's trailing bytes could be spliced into the next request's reassembly window (cross-direction carry-buffer contamination). Each carry buffer is now split into two independent fields keyed by direction (`carry_c2s` / `carry_s2c`). | Protocol | Story | PR | Behavioral Contract | |----------|-------|----|---------------------| | ENIP | STORY-139 | #334 | BC-2.17.EC-X1 | | DNP3 | STORY-140 | #335 | BC-2.15.EC-X1 | | Modbus | STORY-141 | #336 | BC-2.14.EC-X1 | ### Fixed — EC-X2 (`saturating_sub` for clock-backwards window reset) A non-monotonic timestamp (packet re-ordering or NTP step) caused the time-delta computation in the window-reset path to underflow via wrapping subtraction on an unsigned value. The subtraction now uses `saturating_sub`, keeping window-reset logic correct when clocks move backwards. | Protocol | Story | PR | Behavioral Contract | |----------|-------|----|---------------------| | ENIP | STORY-139 | #334 | BC-2.17.EC-X2 | | DNP3 | STORY-140 | #335 | BC-2.15.EC-X2 | | Modbus | STORY-141 | #336 | BC-2.14.EC-X2 | ### Fixed — DNP3 desync-latch complete-predicate The DNP3 desync-latch complete-predicate fired unconditionally, which could produce a spurious desync event on the very first frame of a session before any real desync had occurred. The predicate is now gated on `frame_count == 0` so it only triggers after at least one valid frame has been observed. | Protocol | Story | PR | Behavioral Contract | |----------|-------|----|---------------------| | DNP3 | STORY-142 | #336 | BC-2.15.DESYNC | --- ## Architecture Changes ```mermaid graph TD A[src/analyzer/enip.rs] -->|carry_c2s / carry_s2c split| B[ENIP EC-X1 fix] A -->|saturating_sub delta| C[ENIP EC-X2 fix] D[src/analyzer/dnp3.rs] -->|carry_c2s / carry_s2c split| E[DNP3 EC-X1 fix] D -->|saturating_sub delta| F[DNP3 EC-X2 fix] D -->|frame_count == 0 guard| G[DNP3 desync-latch fix] H[src/analyzer/modbus.rs] -->|carry_c2s / carry_s2c split| I[Modbus EC-X1 fix] H -->|saturating_sub delta| J[Modbus EC-X2 fix] ``` --- ## Story Dependencies ```mermaid graph LR S139[STORY-139 ENIP EC-X1/EC-X2] --> PR334[PR #334 merged] S140[STORY-140 DNP3 EC-X1/EC-X2] --> PR335[PR #335 merged] S141[STORY-141 Modbus EC-X1/EC-X2] --> PR336[PR #336 merged] S142[STORY-142 DNP3 desync-latch] --> PR336 PR334 --> DEV[develop @ a13b5c5] PR335 --> DEV PR336 --> DEV DEV --> REL[release/0.11.0 @ ba31a0c] REL --> MAIN[main] ``` --- ## Spec Traceability ```mermaid flowchart LR BC1[BC-2.14.EC-X1] --> AC1[AC-141-001] --> T1[modbus_detection_tests.rs] --> Code1[modbus.rs carry split] BC2[BC-2.14.EC-X2] --> AC2[AC-141-002] --> T2[modbus_detection_tests.rs] --> Code2[modbus.rs saturating_sub] BC3[BC-2.15.EC-X1] --> AC3[AC-140-001] --> T3[dnp3_f6_story140_mutation_tests.rs] --> Code3[dnp3.rs carry split] BC4[BC-2.15.EC-X2] --> AC4[AC-140-004] --> T4[dnp3_detection_tests.rs] --> Code4[dnp3.rs saturating_sub] BC5[BC-2.15.DESYNC] --> AC5[AC-142-001] --> T5[dnp3_detection_tests.rs] --> Code5[dnp3.rs frame_count guard] BC6[BC-2.17.EC-X1] --> AC6[AC-139-001] --> T6[enip_analyzer_tests.rs] --> Code6[enip.rs carry split] BC7[BC-2.17.EC-X2] --> AC7[AC-139-002] --> T7[enip_analyzer_tests.rs] --> Code7[enip.rs saturating_sub] ``` --- ## Test Evidence - All tests pass on `develop` @ a13b5c5 (CI run 28335634278, green) - `release/0.11.0` adds only CHANGELOG + Cargo.toml version bump on top — no logic changes - Test files modified/added: `enip_analyzer_tests.rs` (+9229 lines), `dnp3_f6_story140_mutation_tests.rs` (+1667), `modbus_detection_tests.rs` (+1539), `enip_e2e_real_pcaps_tests.rs` (+803), `dnp3_f6_story140_group_a_survivors.rs` (+866), plus updates to existing dnp3/modbus/dispatcher test suites --- ## Demo Evidence Per-AC VHS recordings are in `docs/demo-evidence/`: - `STORY-139/evidence-report.md` — ENIP EC-X1/EC-X2 (AC-139-001 through AC-139-004) - `STORY-140/evidence-report.md` — DNP3 EC-X1/EC-X2 + desync-latch (AC-140-001, 004, 005, 008) --- ## Security Review No new attack surface introduced. All changes are defensive: replacing wrapping arithmetic with saturating arithmetic, and splitting shared mutable buffers into direction-keyed fields. No new public API surface, no new deserialization paths, no new network-facing code. --- ## Risk Assessment - **Blast radius:** Contained to the three ICS analyzer structs. No changes to the CLI, dispatcher, pcap reader, or reporting pipeline. - **Performance impact:** Negligible. `saturating_sub` compiles to the same instruction count as wrapping sub on x86-64. The carry buffer split doubles the struct field count for the affected analyzers (2 fields → 4 fields per analyzer), which is a trivially small allocation increase. - **Behavioral change:** Bug-fixes only. Sessions that previously had no cross-direction contamination produce identical output. Sessions that had contamination now produce correct output (previously incorrect behavior is fixed). --- ## AI Pipeline Metadata - Pipeline mode: Feature (gitflow release) - Stories: STORY-139, STORY-140, STORY-141, STORY-142 - Prior CI run on develop: 28335634278 (green) --- ## Pre-Merge Checklist - [x] CHANGELOG entry written (v0.11.0 section in CHANGELOG.md) - [x] Cargo.toml version bumped 0.10.0 → 0.11.0 - [x] Cargo.lock updated - [x] All upstream PRs merged (#334, #335, #336) - [x] CI green on develop @ a13b5c5 - [ ] CI green on release/0.11.0 PR (awaiting CI run) - [x] PR title follows semantic PR convention: `chore: release v0.11.0` - [x] Base branch: main - [x] Merge strategy: squash
- Bump crate version 0.11.0 → 0.11.1 - Add CHANGELOG.md [0.11.1] section (TLS reassembly fix, buffer-saturation telemetry, VP-039 formal hardening, anyhow RUSTSEC-2026-0190 bump) - Update compare links ([Unreleased] and new [0.11.1] entry)
The v0.11.0 release was squash-merged to main (PR #337) without a subsequent back-merge into develop. This merge commit establishes shared history between main and release/0.11.1 so the release PR (#347) can be cleanly merged. Conflict resolution: release/0.11.1 versions kept for all 6 conflicts (CHANGELOG.md, Cargo.toml, Cargo.lock, ci.yml, fuzz/Cargo.toml, fuzz/Cargo.lock) — release branch has the correct v0.11.1 versions and the complete v0.11.0 CHANGELOG section.
chore: release v0.11.1
Bump Cargo.toml + Cargo.lock: 0.11.1 → 0.11.2. Add CHANGELOG.md section for v0.11.2 (2026-07-05) covering the E-21 feature-protocol-coverage delta: protocols subcommand (STORY-152), --coverage-gaps flag / CoverageGapsSummary (STORY-154), KNOWN_PROTOCOLS catalog + partition functions (STORY-151), dispatcher unclassified-protocol gap counters (STORY-153), and F6 formal hardening VP-041/042/043 (#357).
The v0.11.1 release was merged to main (PR #347) via a merge commit that included a history-establishment step (20f3756). That commit is not an ancestor of release/0.11.2, causing a CONFLICTING merge state on PR #358. This merge commit establishes shared history between main and release/0.11.2 so the release PR can be cleanly merged. Conflict resolution: release/0.11.2 versions kept for all 3 conflicts (CHANGELOG.md, Cargo.toml, Cargo.lock) — release branch has the correct v0.11.2 versions and the complete v0.11.2 CHANGELOG section.
chore: release v0.11.2
Zious11
added a commit
that referenced
this pull request
Jul 5, 2026
…SED; v0.11.2 RELEASED; S-7.02 satisfied Cycle feature-protocol-coverage (E-21) CONVERGED/CLOSED (human gate approved 2026-07-05). v0.11.2 RELEASED: PR #358 (release/0.11.2 → main, merge 96ef1ff); tag v0.11.2 (tag object 2852165); GitHub Release Latest. Back-merge PR #359 (main → develop, squash 4a9eba3). Cargo.toml 0.11.2 on main+develop. S-7.02 SATISFIED: recurring [process-gap] finding (STORY-INDEX status not updated on merge, F7 audit P0-001) codified as STORY-155 (E-11, 3 pts, PG-INDEX-DRIFT-001, draft). STATE.md: phase steady-state / status complete / pipeline IDLE. released_version v0.11.2. main_head 96ef1ff. develop_head 4a9eba3. cargo_version 0.11.2. story_index_version v3.14 (108 stories / 694 pts). D-382 added to Decisions Log. F7 Phase Progress row closed. v0.11.2 release row added. Current Phase Steps rotated (D-382 in, D-377 out). Session Resume Checkpoint replaced (IDLE). D-381 checkpoint archived to session-checkpoints.md. Cycle files: - burst-log.md: D-377 step archived + Burst 8 cycle-close narrative - lessons.md: NEW — [codified] PG-INDEX-DRIFT-001 (STORY-155) + 6 [carried] process-gaps - session-checkpoints.md: D-381 checkpoint archived Stories (story-writer artifacts included): - STORY-155.md: NEW draft story (E-11, wave TBD, 3 pts, auto-update STORY-INDEX on merge) - STORY-INDEX.md: v3.13→v3.14 (total_stories 107→108, total_points 691→694, E-11 6→7/24→27 pts) Code-delivery artifacts committed: F6-PROTOCOL-COVERAGE-HARDENING/, f6-hardening-cleanup/, RELEASE-0.11.2/ (previously untracked). Count-propagation sweep: STATE.md frontmatter/operational fields all updated to v3.14/108 stories. Historical references to v3.13 and 107-story counts in D-357/D-381 decisions entries are intentional immutable audit trail.
5 tasks
Zious11
added a commit
that referenced
this pull request
Jul 6, 2026
## Summary Gitflow back-merge: bring `main` HEAD (release v0.11.3, commit 6785716) into `develop` to keep branches in sync per CLAUDE.md "Keeping branches in sync" policy. - Cargo.toml version: 0.11.2 → 0.11.3 - Cargo.lock updated for 0.11.3 - CHANGELOG updated with [0.11.3] release entries ## Traceability | Item | Value | |------|-------| | Pattern | Same as back-merge PR #359 (v0.11.2) | | main HEAD | 6785716 (Merge PR #363 — release/0.11.3) | | develop HEAD before merge | ae93124 | | Merge method | Squash (required_linear_history enabled on develop) | ## Pre-Merge Checklist - [x] Branch created off `main` HEAD (6785716) - [x] Cargo.toml = 0.11.3 on this branch - [x] No code changes — release artifacts only (version bump, Cargo.lock, CHANGELOG) - [ ] CI green - [ ] Squash-merged into develop
Zious11
added a commit
that referenced
this pull request
Jul 6, 2026
## Summary Back-merge release v0.11.4 from `main` into `develop` to keep branches in sync (CLAUDE.md gitflow requirement). - Brings Cargo.toml 0.11.4, Cargo.lock update, and CHANGELOG [0.11.4] into develop - main HEAD: f0f2136 - Follows the same pattern as PR #359 (v0.11.2) and PR #364 (v0.11.3) ## Merge method Squash merge (develop has required_linear_history).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gitflow Back-Merge: v0.11.2 → develop
This PR merges the v0.11.2 release commit from
mainback intodevelopto keep the two branches in sync per the gitflow convention documented in CLAUDE.md.What This Carries
The diff from
develop(6da5456) tomain(96ef1ff) is metadata-only:Cargo.toml: version bump0.11.1→0.11.2Cargo.lock: own-package version line updateCHANGELOG.md:[0.11.2]section addedWhy Required
CLAUDE.md "Keeping branches in sync": After a release or hotfix PR merges into
main, ensuredevelopcontains those commits. Mergemainback intodevelopif needed so the two branches do not diverge.Merge Strategy
Squash merge (required —
develophasrequired_linear_historybranch protection).Traceability