Skip to content

Stop redundant Iroh registration publication - #9350

Merged
azooz2003-bit merged 15 commits into
mainfrom
feat-iroh-registration-floor
Aug 9, 2026
Merged

azooz2003-bit merged 15 commits into
mainfrom
feat-iroh-registration-floor

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Aug 1, 2026 •

Copy link
Copy Markdown
Collaborator

Root cause: Mac and iOS treated every endpoint event as an instruction to republish registration. Sequential events with unchanged reachability repeatedly called challenge, register, discovery, and endpoint attestation.

This change gives both runtimes an actor-owned fingerprint of the last successfully published reachability state. Raw endpoint events publish only when path hints or direct ports changed, or renewal is due. Explicit live discovery and scheduled renewal remain authoritative broker operations. LAN refresh remains immediate.

Regression history:

  • 1d55033 adds failing unchanged-event tests.
  • 84b423e implements state-based publication and adds changed-port safety coverage.

Validation:

  • CmxIrohClientRuntimeTests: 41 passed
  • CmxIrohHostRuntimeTests: 51 passed

This is a principled idempotency boundary, with no request budget, feature gate, or connectivity delay.


Note

Medium Risk
Changes when signed registration and discovery run on the connectivity/broker path; incorrect fingerprint or coalescing logic could delay reachability updates or leave stale broker state, though missing-binding fallback and forced refresh paths mitigate that.

Overview
Mac and iOS Iroh runtimes no longer treat every endpoint network event as a full broker republish. They track lastRegistrationRefreshState via new CmxIrohRegistrationPublicationState, which fingerprints path hints and direct ports and only requires publication when reachability changes, hints are near expiry, or the ~50‑minute renewal window elapses.

Event-driven refreshes compare the live payload to that fingerprint and skip signed register when nothing material changed; LAN refresh stays immediate. Explicit live discovery and scheduled renewal still force authoritative broker work (requiresDiscovery / forcePublication). On iOS, policy resolution can take a read-only discovery path when the fingerprint matches, with fallback to signed registration if the binding is missing from discovery.

Lifecycle cleanup clears publication state on sign-out and teardown (including when preserving binding during sign-out network deactivation) so a stale fingerprint cannot suppress the next session’s publications. Live discovery on the client no longer treats coalesced unchanged-fingerprint no-ops as success without a broker read.

Tests and test brokers were extended for unchanged network storms, port changes, discovery hooks, and sign-out state clearing.

Reviewed by Cursor Bugbot for commit 3cf51a1. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Improved network registration refreshes with read-only discovery when current information is available.
    • Refresh decisions now consider route hints, direct addresses, and expiration timing.
    • Explicit refresh requests can force publication when needed.
  • Bug Fixes
    • Sign-out and network teardown now correctly preserve or clear connection state.
    • Reduced unnecessary registration attempts during refreshes and network changes.
  • Tests
    • Expanded coverage for lifecycle races, discovery failures, stale endpoints, and publication timing.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The runtimes now track registration publication state, use authoritative discovery for eligible refreshes, and register only when required. Lifecycle handling preserves or clears this state with bindings. Tests cover discovery, failures, direct-port changes, queued refreshes, and lifecycle races.

Changes

Registration refresh flow

Layer / File(s) Summary
Publication state and lifecycle handling
Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohRegistrationPublicationState.swift, .../CmxIrohClientRuntime.swift, .../*Lifecycle.swift, .../CmxIrohHostRuntime.swift, .../*SignOut.swift, .../Tests/.../CmxIrohRegistrationPublicationStateTests.swift
The runtimes store payload fingerprints, direct-port data, and refresh deadlines. Lifecycle teardown preserves or clears this state and pending publication flags with the local binding.
Read-only policy resolution
Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/*Policy.swift, .../CmxIrohHostRuntime+PolicyRefresh.swift
Policy resolution validates endpoint identity, builds registration state, uses authoritative discovery without registration when the binding remains valid, and falls back to signed registration when required.
Refresh scheduling and forced publication
Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/*PolicyRefresh.swift, .../CmxIrohHostRuntime+PublicAPI.swift, .../CmxIrohClientRuntime.swift
Refreshes propagate discovery and forced-publication requirements across queued tasks. Non-forced refreshes skip broker registration when publication state is current. Manual and renewal refreshes force publication.
Discovery instrumentation and lifecycle coverage
Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/*
Test infrastructure observes asynchronous discovery calls and supports waiters and injected errors. Tests cover unchanged events, direct-port changes, refresh failures, queued refreshes, and stopped or signed-out runtimes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Runtime as CmxIroh runtime
  participant Refresh as Refresh scheduler
  participant Policy as resolvePolicy
  participant Broker as Iroh broker
  Runtime->>Refresh: Request refresh
  Refresh->>Policy: Resolve policy with discovery requirement
  Policy->>Broker: Discover authoritative policy
  Broker-->>Policy: Discovery result
  alt Publication state is current and binding matches
    Policy-->>Refresh: Return policy without registration
  else Publication is required or binding is missing
    Policy->>Broker: Submit signed registration
    Broker-->>Policy: Registration response
    Policy-->>Refresh: Return policy and publication state
  end
  Refresh-->>Runtime: Complete refresh
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed Production changes add only actor-owned state and an immutable Equatable, Sendable value type; no new protocols, shared mutable Sendable classes, MainActor annotations, or UI-bound access were intr...
Cmux Swift Blocking Runtime ✅ Passed Production diff adds actor-owned state and event-driven refresh flags, but no new semaphore, blocking wait, sleep, delayed dispatch, polling, main sync, or lock; existing registration clock sleeps...
Cmux Browser Automation Off-Main ✅ Passed The PR changes only CmuxIrohTransport files; it does not change TerminalController, ControlCommandExecutionPolicy, or browser socket automation routing.
Cmux Expensive Synchronous Load ✅ Passed The production diff only adds actor-based broker/discovery refresh logic and an in-memory registration fingerprint; it adds no agent-history loaders, disk scans, JSON/JSONL parsing, or interactive...
Cmux Cache Substitution Correctness ✅ Passed The diff adds actor-owned in-memory publication state, not a persistence/history/undo path; cold state forces publication, live payloads are rebuilt, and discovery uses revision-checked authoritati...
Cmux No Hacky Sleeps ✅ Passed The changed files are Swift files only; the rule explicitly scopes TypeScript, JavaScript, shell, and non-Swift runtime scripts.
Cmux Algorithmic Complexity ✅ Passed The new fingerprint sorts at most 16 path hints and compares two direct-port fields; discovery operations use single linear scans, with no nested or per-target rescans.
Cmux Swift Concurrency ✅ Passed Runtime diff adds no Dispatch, Combine, or completion-handler patterns. Refresh Tasks remain actor-owned, stored, and cancelled on teardown; new TaskGroup/continuation use is test-only synchronizat...
Cmux Swift @Concurrent ✅ Passed Changed async helpers remain actor-isolated on CmxIrohClientRuntime/CmxIrohHostRuntime and access actor state; the diff adds no nonisolated async or invalid @concurrent code.
Cmux Swift Package Boundaries ✅ Passed All changed production Swift files are in the reusable CmuxIrohTransport SwiftPM target; no app-target Sources files changed, and related tests remain in its test target.
Cmux Swiftpm Lockfiles ✅ Passed The PR diff from 546b0bb to HEAD changes only CmuxIrohTransport source and tests; it contains no Package.swift, Package.resolved, Xcode project, .gitignore, or workflow changes.
Cmux Swift Logging ✅ Passed The full PR diff adds no print, debugPrint, dump, NSLog, Logger, stdout, or ad hoc diagnostic file logging in changed production Swift files.
Cmux User-Facing Error Privacy ✅ Passed The production diff adds no user-facing error, alert, command output, or API error text; new throws are internal runtime enum cases and refresh failures remain classified or handled internally.
Cmux Full Internationalization ✅ Passed Production changes add no user-facing text or localization keys; only registration state logic and developer comments changed. The remaining literals are test fixtures, with no catalog or web local...
Cmux Swiftui State Layout ✅ Passed The PR changes only Iroh transport actors, helpers, and tests; it adds no SwiftUI views, observation state, layout measurement, lazy-row store references, or render-time state writes.
Cmux Architecture Rethink ✅ Passed The change keeps publication state and refresh flags inside the existing client/host actors, uses shared scheduling paths, and adds no production sleeps, locks, polling, observers, or side-channel...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR changes only Iroh transport logic and tests; it adds no NSWindow, NSPanel, NSWindowController, SwiftUI Window, WindowGroup, or cmux window identifier.
Cmux Source Artifacts ✅ Passed The full PR range changes only Swift source and test files under Packages/Shared/CmuxIrohTransport; no artifact, cache, temp, build-output, or scratch paths appear.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Changed production Swift adds runtime publication state and helpers used by product refresh flows; no DEBUG/test guards, seam-named members, visibility widening, or test-only callers were found.
Cmux No Ambient Global State ✅ Passed Production additions keep mutable state on CmxIrohClientRuntime/CmxIrohHostRuntime actors; CmxIrohRegistrationPublicationState is constructable with instance behavior, and only private static const...
Title check ✅ Passed The title clearly summarizes the primary change: preventing redundant Iroh registration publication.
Description check ✅ Passed The description clearly explains the cause, implementation, behavior, risks, and test results, but omits several template sections such as the checklist and demo video.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-iroh-registration-floor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@azooz2003-bit
azooz2003-bit force-pushed the feat-iroh-registration-floor branch from 7a36665 to adb62e2 Compare August 3, 2026 21:40
@azooz2003-bit azooz2003-bit changed the title Pace Iroh registration challenges per slot Coalesce Iroh client registration refreshes Aug 3, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime+Policy.swift (1)

98-119: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Move payload signing after the read-only eligibility check.

signer.prepare(payload:) runs unconditionally at line 102, before the code checks allowReadOnlyRegistrationRefresh and shouldUseReadOnlyRegistrationRefresh. When the read-only path applies, prepared is computed and then discarded. This signing work runs on every foreground activation and every network-change refresh, not only when a signed mutation is actually needed.

Move the CmxIrohRegistrationSigner creation and prepare(payload:) call after the read-only check, so signing only happens on the branch that uses it.

♻️ Proposed reordering
-        let signer = try CmxIrohRegistrationSigner(
-            identity: configuration.identity,
-            endpointID: expectedEndpointID.endpointID
-        )
-        let prepared = try signer.prepare(payload: payload)
-        let refreshState = Self.registrationRefreshState(
+        let refreshState = Self.registrationRefreshState(
             payload: payload,
             now: now()
         )
         if allowReadOnlyRegistrationRefresh,
            shouldUseReadOnlyRegistrationRefresh(refreshState, at: now()) {
             do {
                 return try await readOnlyResolvedPolicy(
                     expectation: expectation,
                     offlineExpectation: offlineExpectation
                 )
             } catch CmxIrohClientRuntimeError.localBindingMissingFromDiscovery {
                 // The server no longer has this binding. Fall through to a
                 // signed mutation so the client self-heals instead of staying
                 // read-only forever.
             }
         }
+        let signer = try CmxIrohRegistrationSigner(
+            identity: configuration.identity,
+            endpointID: expectedEndpointID.endpointID
+        )
+        let prepared = try signer.prepare(payload: payload)
         let registration: CmxIrohRegistrationResponse?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime`+Policy.swift
around lines 98 - 119, Move the CmxIrohRegistrationSigner creation and
signer.prepare(payload:) call below the read-only eligibility block in the
registration flow. Keep the readOnlyResolvedPolicy return and
localBindingMissingFromDiscovery fallback unchanged, and ensure the signer and
prepared values are created only on the subsequent signed-mutation path where
they are used.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime`+Policy.swift:
- Around line 98-119: Move the CmxIrohRegistrationSigner creation and
signer.prepare(payload:) call below the read-only eligibility block in the
registration flow. Keep the readOnlyResolvedPolicy return and
localBindingMissingFromDiscovery fallback unchanged, and ensure the signer and
prepared values are created only on the subsequent signed-mutation path where
they are used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ac89a7c8-a56e-4db6-bfcf-dcbe20331818

📥 Commits

Reviewing files that changed from the base of the PR and between 8cc5dc4 and adb62e2.

📒 Files selected for processing (7)
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime+Lifecycle.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime+Policy.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime+PolicyRefresh.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/TestIrohClientBroker.swift

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@azooz2003-bit azooz2003-bit changed the title Coalesce Iroh client registration refreshes Stop redundant Iroh registration publication Aug 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime+SignOut.swift (1)

38-48: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Clear lastRegistrationRefreshState together with localBinding on successful sign-out.

At line 39, performSignOut clears localBinding = nil but does not clear lastRegistrationRefreshState. The client's equivalent method, CmxIrohClientRuntime+Lifecycle.swift performSignOut, clears both fields together at the same point. Leaving lastRegistrationRefreshState set after the binding it was derived from no longer exists violates the requirement to clear or preserve cached publication state consistently with the binding during sign-out.

resolveInitialPolicy currently forces a full signed registration on every start(), so this stale value is overwritten before it is read. Fix this now so a future change to the startup path (for example, extending the read-only optimization to initial resolution) does not silently reintroduce stale-state behavior.

🔧 Proposed fix
         localBinding = nil
+        lastRegistrationRefreshState = nil
         lifecyclePhase = .inactive
Based on learnings, applying `.github/review-bot-rules/reliability-single-source-of-truth.md`: "Keep cached publication state strictly derived from the authoritative registration/payload data; clear or preserve it consistently with the binding during sign-out, teardown, start, and foreground transitions."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime`+SignOut.swift
around lines 38 - 48, Update performSignOut to clear
lastRegistrationRefreshState immediately alongside localBinding, matching the
client runtime’s sign-out behavior. Preserve the existing lifecycle snapshot and
operation-reset logic.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime`+Policy.swift:
- Around line 78-102: Move the CmxIrohRegistrationSigner initialization and
signer.prepare(payload:) calls in the registration flow to after the
allowReadOnlyRegistrationRefresh/shouldUseReadOnlyRegistrationRefresh branch.
Keep payload and registrationRefreshState creation before the branch, and
preserve the existing read-only return and fallback behavior so signing occurs
only when the signed mutation path is needed.

In
`@Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime`+PolicyRefresh.swift:
- Around line 84-96: Ensure endpoint-instance replacement forces a signed
registration even when route keys and direct ports are unchanged. Update
CmxIrohRegistrationPublicationState and the non-discovery refresh flow around
registrationRefreshState, requiresPublication, and
shouldUseReadOnlyRegistrationRefresh to track runtimeGeneration (or equivalent
endpoint-instance generation) and prevent read-only refreshed policy until that
generation is published.

In
`@Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime`+PolicyRefresh.swift:
- Around line 386-409: Update refreshRegistration so non-forced refreshes do not
return solely because state.requiresPublication(after:now:) is false. Mirror the
client read-only shortcut by running authoritative discovery without requiring
publication, then force a signed registration refresh when the local host
binding is absent from the discovered result; preserve the existing
publication-required behavior for forced refreshes.

---

Outside diff comments:
In
`@Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime`+SignOut.swift:
- Around line 38-48: Update performSignOut to clear lastRegistrationRefreshState
immediately alongside localBinding, matching the client runtime’s sign-out
behavior. Preserve the existing lifecycle snapshot and operation-reset logic.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 98dc1f66-1f47-4cca-b140-c29a103dfb4a

📥 Commits

Reviewing files that changed from the base of the PR and between f4263ae and 84b423e.

📒 Files selected for processing (16)
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime+Lifecycle.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime+Policy.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime+PolicyRefresh.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohClientRuntime.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime+PolicyRefresh.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime+PublicAPI.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime+SignOut.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohHostRuntime.swift
  • Packages/Shared/CmuxIrohTransport/Sources/CmuxIrohTransport/CmxIrohRegistrationPublicationState.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohHostRuntimeLifecycleRaceTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohHostRuntimeLifecycleTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohHostRuntimePolicyTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/TestIrohClientBroker.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/TestIrohEndpoint.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift (1)

264-267: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Verify the changed direct port in both publication payloads.

Both tests prove only that a second broker registration occurred. They do not prove that the changed direct port was serialized, so stale-port publication can pass.

  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift#L264-L267: inspect the second prepared registration and assert direct port 50909.
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohHostRuntimeLifecycleTests.swift#L603-L608: assert registrationDirectPorts equals IPv4 port 50909 with no IPv6 port.

Based on the existing prepared-registration assertion pattern in Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohHostRuntimeLifecycleTests.swift Lines 480-486.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift`
around lines 264 - 267, Verify the changed direct port in both registration
payloads: in
Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift:264-267,
inspect the second prepared registration and assert direct port 50909; in
Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohHostRuntimeLifecycleTests.swift:603-608,
assert registrationDirectPorts contains IPv4 port 50909 and no IPv6 port,
following the existing prepared-registration assertion pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift`:
- Around line 264-267: Verify the changed direct port in both registration
payloads: in
Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift:264-267,
inspect the second prepared registration and assert direct port 50909; in
Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohHostRuntimeLifecycleTests.swift:603-608,
assert registrationDirectPorts contains IPv4 port 50909 and no IPv6 port,
following the existing prepared-registration assertion pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5ae3a905-015b-4f42-847a-14b6eea01870

📥 Commits

Reviewing files that changed from the base of the PR and between 1e74a7f and 12710d3.

📒 Files selected for processing (2)
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohClientRuntimeLifecycleRaceTests.swift
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohHostRuntimeLifecycleTests.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohRegistrationPublicationStateTests.swift`:
- Around line 90-116: Add an IPv6-only direct-port publication test alongside
changedDirectPortsRequirePublication, using state to create two registrations
with the same hints and IPv4 value but different ipv6 values, then assert the
changed state requires publication after the original.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ece39c90-6b30-47ae-9bbc-cae9720a5c26

📥 Commits

Reviewing files that changed from the base of the PR and between 12710d3 and 21fc81a.

📒 Files selected for processing (1)
  • Packages/Shared/CmuxIrohTransport/Tests/CmuxIrohTransportTests/CmxIrohRegistrationPublicationStateTests.swift

azooz2003-bit and others added 4 commits August 7, 2026 13:42
A live discovery that observes an in-flight unchanged-fingerprint refresh
and its coalesced successors can return .refreshed without any
authoritative broker read. TestIrohEndpoint gains an armable address()
gate so each raced refresh is deterministically held in flight.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Observing a coalesced successor no longer forfeits the live discovery
request's right to schedule one discovery-forced refresh, and a
no-op .refreshed outcome without a generation advance no longer
satisfies the request or masks an earlier real failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… IPv6 ports

Payload signing now happens only after the read-only eligibility gate
declines, so the read-only fast path no longer performs a discarded
signature. The publication-state test also pins IPv6-only direct-port
changes as requiring publication.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 03bae91. Configure here.

@azooz2003-bit

Copy link
Copy Markdown
Collaborator Author

Review round addressed on top of a fresh main merge (3ca07da):

  • fd7066b + 808524b fix the Cursor high-severity finding: a live discovery racing an in-flight unchanged-fingerprint refresh and its coalesced successors could return .refreshed without any authoritative broker read. The regression test holds each raced refresh in flight via an armable address() gate; the fix keeps the request's right to schedule one discovery-forced refresh across successors and stops no-op .refreshed outcomes from satisfying the request or masking real failures.
  • 03bae91 reorders signing after the read-only gate and pins IPv6-only direct-port changes in the publication-state test.

CmuxIrohTransport: 590/590 tests pass locally.

azooz2003-bit and others added 2 commits August 7, 2026 20:45
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirrors the client sign-out path so a stale fingerprint cannot suppress
the next session's non-forced publications.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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