Skip to content

chore: back-merge release v0.11.2 into develop#359

Merged
Zious11 merged 7 commits into
developfrom
chore/backmerge-v0.11.2
Jul 5, 2026
Merged

chore: back-merge release v0.11.2 into develop#359
Zious11 merged 7 commits into
developfrom
chore/backmerge-v0.11.2

Conversation

@Zious11

@Zious11 Zious11 commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Gitflow Back-Merge: v0.11.2 → develop

This PR merges the v0.11.2 release commit from main back into develop to keep the two branches in sync per the gitflow convention documented in CLAUDE.md.

What This Carries

The diff from develop (6da5456) to main (96ef1ff) is metadata-only:

  • Cargo.toml: version bump 0.11.10.11.2
  • Cargo.lock: own-package version line update
  • CHANGELOG.md: [0.11.2] section added

Why Required

CLAUDE.md "Keeping branches in sync": After a release or hotfix PR merges into main, ensure develop contains those commits. Merge main back into develop if needed so the two branches do not diverge.

Merge Strategy

Squash merge (required — develop has required_linear_history branch protection).

Traceability

Item Value
Release PR #358
main HEAD 96ef1ff
develop base 6da5456
Prior back-merge #348 (v0.11.1)

Zious11 added 7 commits June 29, 2026 07:45
## 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.
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.
@Zious11 Zious11 merged commit 4a9eba3 into develop Jul 5, 2026
27 checks passed
@Zious11 Zious11 deleted the chore/backmerge-v0.11.2 branch July 5, 2026 13:57
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.
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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant