Skip to content

CAMEL-26322: camel-as2 - scope the async MDN allow-list to host and port, and add an option to require https - #28527

Merged
davsclaus merged 6 commits into
apache:mainfrom
oscerd:fix/CAMEL-26322
Oct 29, 2026
Merged

davsclaus merged 6 commits into
apache:mainfrom
oscerd:fix/CAMEL-26322

Conversation

@oscerd

@oscerd oscerd commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

When camel-as2 requests an asynchronous MDN (Message Disposition Notification),
AS2AsynchronousMDNManager.send() resolves the delivery address from the sender-supplied
Receipt-Delivery-Option URI and opens a connection to it. The asyncMdnAllowedHosts option on
AS2Configuration governs whether the MDN is delivered to the resolved address and whether the
configured MDN credentials (mdnUserName / mdnPassword / mdnAccessToken) are attached.

send() resolves both the host and the port of the delivery address (the port via
uri.getPort(), defaulted to 80 or 443 by scheme), but the allow-list match compared only the
host. The resolved port was used to open the socket but was never matched against the list, so
every port on a listed host was treated the same — both for delivery and for attaching the
credentials.

Change

  • AS2AsynchronousMDNManager now matches the full authority — host and port — of the resolved
    delivery address. The single allow decision that gates the connection and the attachment of the
    credentials now accounts for the port.
  • Each asyncMdnAllowedHosts entry may carry an optional port in host:port form. A bare-host
    entry (for example partner.example) matches only the default port for the scheme (80 for
    http, 443 for https); a non-default port is listed explicitly (for example
    partner.example:8443). IPv6 literals are supported ([::1] or [::1]:8443).
  • The asyncMdnAllowedHosts description on AS2Configuration is updated to document the
    host[:port] form, the default-port rule and the IPv6 form, and the catalog / component /
    endpoint-dsl metadata is regenerated. The IPv6 form is described in words ("an IPv6 literal is
    written in square brackets, as in a URL, optionally followed by :port") because the catalog
    generator drops bracket characters from option descriptions; the literal [::1] / [::1]:8443
    examples are in the component documentation and the upgrade guide.
  • When an asynchronous MDN is delivered without the credentials (no asyncMdnAllowedHosts set), the
    warning names the delivery authority as an entry that can be copied to the list: host:port, with
    an IPv6 host in square brackets (for example [::1]:8443).
  • A new opt-in option asyncMdnRequireHttps (default false) is added. When set, an asynchronous
    MDN whose delivery address does not use https is refused before the connection is opened and
    before the credentials are attached, so the configured MDN credentials are never sent in cleartext
    to a sender-chosen address. The option applies per consumer endpoint, like asyncMdnAllowedHosts.

Tests

New and updated JUnit methods in AS2AsynchronousMDNManagerDeliveryAddressTest:

  • a delivery address whose host and port both match an entry is accepted;
  • a different port on a listed (bare-host) entry is refused, and the credentials are not attached;
  • a bare-host entry matches the default port for its scheme (checked on the matcher directly, without
    opening a connection);
  • an IPv6 literal matches its allow-list entry on host and port;
  • with asyncMdnRequireHttps set, a plain-http delivery address is refused and an https address is
    accepted; by default (option off) http is still accepted;
  • the authority the warning names is host:port, with an IPv6 host in square brackets, and once
    listed it matches the authority it was written for.

AS2ConsumerConfigurationMdnSettingsTest checks that asyncMdnRequireHttps is carried by the
consumer configuration, and that the constructors without it default it to false.

The existing camel-as2-component tests that deliver an asynchronous MDN to a random local port
(AS2ServerBasicAuthHeaderTest, AS2ServerBearerAuthHeaderTest, AS2AsyncMdnBasicAuthHeaderTest,
AS2AsyncMdnTokenAuthHeaderTest, AS2AsyncMdnContextReuseTest and
AS2ServerTwoConsumerAsyncMdnSettingsTest) now list host:port in asyncMdnAllowedHosts instead of a bare
host, as a bare-host entry matches only the default port.

Documentation

  • An upgrade-guide note for the default-port behaviour change is added on main in
    docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc.
  • as2-component.adoc gets a short "Delivering asynchronous MDNs" section with the entry forms,
    including the bracketed IPv6 examples.

Claude Code on behalf of oscerd

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM. Solid security-hardening PR — the host+port authority matching and asyncMdnRequireHttps option are correctly implemented, properly threaded through all assembly paths, and well tested.

One minor Javadoc gap: the updated asyncMdnAllowedHosts description documents host:port form but doesn't mention IPv6 bracket notation, which is non-obvious. See inline comment.

⚠️ Pre-fix validation: dynamic check skipped (build takes too long for this environment). Static trace: httpIsRefusedWhenHttpsIsRequired and httpIsAcceptedWhenHttpsIsNotRequired tests directly exercise the requireHttps && !https branch introduced by the fix. The assertion e.getMessage().contains("asyncMdnRequireHttps") would only trigger if that branch fires, confirming the tests exercise the corrected code path.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-as2/camel-as2-api
  • components/camel-as2/camel-as2-component
  • docs
  • dsl/camel-endpointdsl

🔁 1 test passed only after a retry on JDK 21 (1 retried attempt)

Recovered flaky tests on JDK 21 (1)
Module Test Failed attempts First failure
dsl/camel-jbang/camel-jbang-plugin-tui MonitorStartupTest.browserOnlyServesUntilTheServerStops 1 Connection refused (connect failed)

ℹ️ These tests did not fail the build. Surefire retried them and they passed.
Retries are enabled project-wide by surefire.rerunFailingTestsCount in parent/pom.xml.


🔬 Scalpel shadow comparison — Scalpel: 9 of 708 tested, 24 compile-only — current: 9 all tested

Maveniverse Scalpel detected 9 affected modules (current approach: 9).

Skip-tests mode would test 9 modules (5 direct + 7 downstream), skip tests for 24 (generated code, meta-modules)

Modules Scalpel would test (9)
  • camel-as2 ← components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2AsyncMDNServerManagerEndpointConfigurationConfigurer.java, components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2ClientManagerEndpointConfigurationConfigurer.java, components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2ConfigurationConfigurer.java, components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2EndpointConfigurer.java, components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2EndpointUriFactory.java, components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2ServerManagerEndpointConfigurationConfigurer.java, components/camel-as2/camel-as2-component/src/generated/resources/META-INF/org/apache/camel/component/as2/as2.json, components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc, components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java, components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Consumer.java, components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/internal/AS2ConnectionHelper.java, components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2AsyncMdnBasicAuthHeaderTest.java, components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2AsyncMdnContextReuseTest.java, components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2AsyncMdnTokenAuthHeaderTest.java, components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ServerBasicAuthHeaderTest.java, components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ServerBearerAuthHeaderTest.java, components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ServerTwoConsumerAsyncMdnSettingsTest.java
  • camel-as2-api ← components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsynchronousMDNManager.java, components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java, components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2AsynchronousMDNManagerDeliveryAddressTest.java, components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2ConsumerConfigurationMdnSettingsTest.java
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-catalog
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
Modules with tests skipped (24)
  • apache-camel
  • camel-allcomponents
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (36 modules, 5m 21s total)

Total reactor time: 5m 21s

Module Duration Status
Camel :: AS2 :: Component 46.3s SUCCESS
Camel :: JBang :: MCP 39.3s SUCCESS
Camel :: JBang :: Plugin :: Validate 28.8s SUCCESS
Camel :: YAML DSL :: Validator 23.2s SUCCESS
Camel :: Catalog :: Camel Catalog 19.8s SUCCESS
Camel :: YAML DSL 19.8s SUCCESS
Camel :: AS2 :: API 19.3s SUCCESS
Camel :: Component DSL 18.1s SUCCESS
Camel :: JBang :: Plugin :: Testing 14.9s SUCCESS
Camel :: Docs 12.7s SUCCESS
Camel :: JBang :: Plugin :: Kubernetes 12.6s SUCCESS
Camel :: Kamelet Main 11.4s SUCCESS
Camel :: Catalog :: Camel Report Maven Plugin 8.2s SUCCESS
Camel :: YAML DSL :: Deserializers 6.7s SUCCESS
Camel :: Catalog :: Camel Route Parser 6.3s SUCCESS
Camel :: YAML DSL :: Validator Maven Plugin 6.2s SUCCESS
Camel :: Catalog :: Suggest (deprecated) 5.0s SUCCESS
Camel :: All Components Sync point 4.5s SUCCESS
Camel :: Catalog :: Maven 3.0s SUCCESS
Camel :: Assembly 2.6s SUCCESS
Camel :: YAML DSL :: Maven Plugins 2.0s SUCCESS
Camel :: Endpoint DSL :: Support 2.0s SUCCESS
Camel :: JBang :: Integration tests 1.3s SUCCESS
Camel :: JBang :: Plugin :: Generate 1.1s SUCCESS
Camel :: Coverage 1.1s SUCCESS
Camel :: JBang :: Plugin :: Edit 1.0s SUCCESS
Camel :: JBang :: Plugin :: MCP 0.9s SUCCESS
Camel :: JBang :: Main 0.9s SUCCESS
Camel :: Catalog :: Dummy Component 0.9s SUCCESS
Camel :: Catalog :: Console 0.8s SUCCESS
Camel :: Launcher :: Container 0.7s SUCCESS
Camel :: Endpoint DSL n/a
Camel :: Integration Tests n/a
Camel :: JBang :: Core n/a
Camel :: JBang :: Plugin :: TUI n/a
Camel :: Launcher n/a

Top 20 slowest modules:

  • Camel :: AS2 :: Component (46.3s)
  • Camel :: JBang :: MCP (39.3s)
  • Camel :: JBang :: Plugin :: Validate (28.8s)
  • Camel :: YAML DSL :: Validator (23.2s)
  • Camel :: Catalog :: Camel Catalog (19.8s)
  • Camel :: YAML DSL (19.8s)
  • Camel :: AS2 :: API (19.3s)
  • Camel :: Component DSL (18.1s)
  • Camel :: JBang :: Plugin :: Testing (14.9s)
  • Camel :: Docs (12.7s)
  • Camel :: JBang :: Plugin :: Kubernetes (12.6s)
  • Camel :: Kamelet Main (11.4s)
  • Camel :: Catalog :: Camel Report Maven Plugin (8.2s)
  • Camel :: YAML DSL :: Deserializers (6.7s)
  • Camel :: Catalog :: Camel Route Parser (6.3s)
  • Camel :: YAML DSL :: Validator Maven Plugin (6.2s)
  • Camel :: Catalog :: Suggest (deprecated) (5.0s)
  • Camel :: All Components Sync point (4.5s)
  • Camel :: Catalog :: Maven (3.0s)
  • Camel :: Assembly (2.6s)

⚙️ View full build and test results

…ort, and add an option to require https

The asyncMdnAllowedHosts allow-list now matches the full authority - host and port - of the
asynchronous MDN delivery address, instead of the host alone. Each entry is a host with an optional
port in host:port form; a bare-host entry matches only the default port for the scheme (80 or 443),
so a non-default port is listed explicitly as host:port. This gates both the delivery connection and
the attachment of the configured MDN credentials on the port as well as the host. The option
description and the upgrade guide are updated for the default-port behaviour.

A new opt-in option asyncMdnRequireHttps (default false) is added: when set, an asynchronous MDN
whose delivery address does not use https is refused before the connection is opened and before the
credentials are attached, so the configured MDN credentials are never sent in cleartext to a
sender-chosen address.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

TL;DR

Comment — scoping the async MDN allow-list to host and port, and the new asyncMdnRequireHttps, are correct and fail closed: one authorityIsAllowed decision gates both the connection and the credentials, and the https check runs before the socket opens. Generated files and the upgrade guide entry are in place.

Blockers: None.

Other findings: 1 nit (open gnodet-bot thread), 3 suggestions, 1 stale comment — see below.

Findings

  1. The IPv6 bracket form is not documented (gnodet-bot thread on AS2Configuration.java:763, still open). The matcher handles [::1] and [::1]:8443 (AS2AsynchronousMDNManager isAllowedAuthority), and anIpv6AllowListEntryIsMatchedOnHostAndPort tests it, but the asyncMdnAllowedHosts javadoc (the catalog description) and the upgrade guide only say host:port. Applying the suggestion needs the catalog, component JSON and endpoint DSL regenerated.

  2. The WARN hint can point to an entry that does not match. AS2AsynchronousMDNManager.java:254-256 logs only the host: "credentials not sent to sender-supplied host {}: set asyncMdnAllowedHosts to authorise it". A bare-host entry now matches only port 80/443, so an operator who copies that host while the partner uses e.g. 4080 gets every MDN refused. Logging host + ":" + port gives them the entry to write.

  3. The wiring of asyncMdnRequireHttps is not tested. It passes from AS2Consumer / AS2ConnectionHelper through AS2ConsumerConfiguration and AS2ServerConnection into the manager, and every construction site passes it, but no test checks isAsyncMdnRequireHttps() or that the shorter constructors default it to false. AS2ConsumerConfigurationMdnSettingsTest already covers the other MDN settings that way.

  4. aBareHostEntryMatchesTheDefaultPort reaches the network. The authority is allowed, so send() opens new Socket("partner.example", 80) with the test credentials attached. It passes because .example fails DNS quickly; behind a resolver that rewrites failed lookups, or a firewall that drops traffic, it waits for the OS connect timeout (no connect timeout is set). Testing isAllowedAuthority directly for the port-80 case avoids that.

  5. Stale comment: AS2AsynchronousMDNManager.java:200 still says "Plain http is always allowed", which is no longer true when asyncMdnRequireHttps is set (line 211).

CI: the previous build (21, false) failures were AuthoringToolsLenientTest in camel-jbang-core, a break on main fixed by 57b17bd; the branch is rebased onto it and CI is running again.

Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying. It does not replace specialized review tools or static analysis.

…ty matching

- Document IPv6 bracket notation in AS2Configuration and upgrade guide
- Log both host and port in async MDN authority warning
- Add unit tests for asyncMdnRequireHttps wiring in consumer configuration
- Test bare-host authority matching directly without opening network sockets

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd

oscerd commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

Addressed review feedback:

  • Explicitly documented IPv6 literal bracket notation ([::1] and [::1]:8443) in AS2Configuration Javadoc and the 4.24 migration guide.
  • Included both host and port in the async MDN authority warning log.
  • Added unit tests for asyncMdnRequireHttps wiring in AS2ConsumerConfigurationMdnSettingsTest.
  • Tested bare-host default port matching in AS2AsynchronousMDNManagerDeliveryAddressTest directly via isAllowedAuthority without opening sockets.

Claude Code on behalf of oscerd

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Following up on my earlier review — the previous finding (IPv6 bracket notation in asyncMdnAllowedHosts Javadoc) has been addressed. The davsclaus review findings from the prior iteration are also all fixed in this update: host:port authority in the WARN log, asyncMdnRequireHttps wiring tests, direct isAllowedAuthority() call in the bare-host port test, and the stale "Plain http is always allowed" comment.

One remaining inconsistency: the generated catalog/component JSON and endpoint DSL Javadoc for asyncMdnAllowedHosts are missing the IPv6 bracket notation detail that was added to AS2Configuration.java. The setter Javadoc at line 764 now reads:

Each entry is a host with an optional port in host:port form (IPv6 literals use bracket notation, for example [::1] or [::1]:8443); a bare-host entry…

But the generated catalog/camel-catalog/…/as2.json, camel-as2-component/…/as2.json, and AS2EndpointBuilderFactory.java all say:

Each entry is a host with an optional port in host:port form; a bare-host entry…

The IPv6 parenthetical is absent. This means the codegen was run against an earlier version of the Javadoc and the metadata wasn't regenerated after the IPv6 annotation was added. Operators configuring asyncMdnAllowedHosts via IDE tooling or the component catalog will see incomplete format documentation. Running the Camel code generator again after the Javadoc update will fix this.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

✅ Generated files are up to date

An earlier CI run reported uncommitted generated changes; the latest run no longer does.

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Following up on my earlier review — 4 of the 5 previous findings have been addressed in this update.

Addressed ✅:

  • davsclaus finding 2 — WARN log now includes both host and port ({}:{}).
  • davsclaus finding 3 — asyncMdnRequireHttps wiring is now tested in AS2ConsumerConfigurationMdnSettingsTest.
  • davsclaus finding 4 — aBareHostEntryMatchesTheDefaultPort now calls isAllowedAuthority() directly, no longer touches the network.
  • davsclaus finding 5 — Stale "Plain http is always allowed" comment replaced with accurate text.

Still open ⚠️:

  • The generated catalog JSON and endpoint DSL Javadoc show ::1 or ::1:8443 (brackets stripped by codegen) instead of [::1] or [::1]:8443. The source Javadoc in AS2Configuration.java and the upgrade guide are correct. See inline comment.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

…n catalog and endpoint dsl

- Wrap IPv6 bracket examples in {@code} in AS2Configuration javadoc
- Restore [::1] and [::1]:8443 in as2.json and AS2EndpointBuilderFactory

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Following up on my earlier review — all previous findings are now addressed.

The last open item — IPv6 bracket notation stripped by codegen in the catalog JSON and endpoint DSL — is fixed in commit e0003b4 by wrapping the IPv6 examples in {@code} tags in the source Javadoc, which correctly preserves [::1] and [::1]:8443 through the code generator into the catalog and DSL artifacts. LGTM.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Following up on my earlier review — the new commit (0d22bbb) is a pure codegen refresh: it regenerates the catalog JSON and endpoint DSL Javadoc with the {code ::1} fix from the prior source commit (e0003b4). No logic changes. All previous findings remain addressed.

LGTM.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

TL;DR

Verdict: Nearly there: four of my five earlier points are fixed, and the matcher, wiring and tests look good. One documentation item came back in the last regen.

Blockers: None

Other findings: 1 non-blocking (the IPv6 example in the generated catalog/DSL reads {code ::1}), 1 suggestion.

Status of my earlier points:

  1. IPv6 bracket form: partially. The AS2Configuration javadoc and the upgrade guide are right; the generated text is not (below).
  2. WARN names the authority: fixed ({}:{}).
  3. asyncMdnRequireHttps wiring tests: fixed (configurationWithRequireHttps plus the assertFalse checks).
  4. Bare-host test without network: fixed (direct isAllowedAuthority call).
  5. Stale "Plain http is always allowed" comment: fixed.

Non-blocking: the IPv6 example in the catalog and Endpoint DSL now reads {code ::1} or {code ::1:8443} (both as2.json files and AS2EndpointBuilderFactory.java:669-670, :1939-1940). The bracketed text in e0003b4 was a hand edit to generated files, and the following Regen (0d22bbb) replaced it with the generator output. JavadocHelper.sanitizeJavaDoc (camel-tooling-util) keeps only identifier characters and .,-='/\!&%():;#${}, so [, ] and @ are dropped and {@code [::1]} cannot survive. Since ::1:8443 is itself a valid IPv6 address and an unbracketed entry is taken as a host, an operator copying the catalog example would have every MDN refused. A hint: describe the form without bracket characters in the javadoc, e.g. "an IPv6 literal is written in square brackets, as in a URL, optionally followed by :port", keep the literal [::1] / [::1]:8443 examples in the upgrade guide (and as2-component.adoc), then regenerate. The earlier gnodet-bot thread on this was resolved, but the text is not fixed at the head.

Suggestion: for an IPv6 destination the WARN prints ::1:8443, because normalizeHost stripped the brackets, which is the form the allow-list does not accept. Wrapping the host in brackets when it contains : would give operators an entry they can copy.


Reviewed with Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

…in words, and bracket an IPv6 host in the warning

The catalog generator keeps only identifier characters and a few
punctuation characters in an option description, so the bracketed IPv6
examples in the asyncMdnAllowedHosts javadoc came out as "{code ::1}"
in the catalog and the Endpoint DSL. Describe the IPv6 form in words
instead and regenerate. The literal [::1] and [::1]:8443 examples stay
in the upgrade guide, and as2-component.adoc gets a short section with
the entry forms.

The warning logged when the credentials are not sent named an IPv6
destination as ::1:8443, which the allow-list reads as another IPv6
address. Write the host in square brackets ([::1]:8443), so the warning
names an entry the operator can copy. The matching logic is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd

oscerd commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the follow-up review. Both points are addressed in "CAMEL-26322: camel-as2 - write the IPv6 form of asyncMdnAllowedHosts in words, and bracket an IPv6 host in the warning".

1. The IPv6 example in the catalog and Endpoint DSL

Confirmed. The option description goes through JavadocHelper.sanitizeDescription (camel-tooling-util), which keeps only identifier characters and .,-='/\!&%():;#${}, and its {@...} unwrapping pattern does not match [::1]. So {@code [::1]} can only come out as {code ::1}: run through the sanitizer, the old text gives exactly what the head carried.

  • The asyncMdnAllowedHosts javadoc no longer uses bracket characters: "Each entry is a host with an optional port in host:port form; an IPv6 literal is written in square brackets, as in a URL, optionally followed by :port." I ran the whole new description through sanitizeDescription before the regen, and it comes out unchanged.
  • Both as2.json copies and AS2EndpointBuilderFactory are regenerated from it by the full reactor, with no hand edits.
  • The literal examples stay in the pages that are not generated from the javadoc. The upgrade-guide note keeps [::1] / [::1]:8443 unchanged, as it was already right. as2-component.adoc had no example, so it gets a short "Delivering asynchronous MDNs" section that lists the entry forms with [::1] and [::1]:8443, and notes that an unbracketed ::1:8443 is read as another IPv6 address, not as ::1 with a port. The catalog copy of the page is regenerated.

2. The warning prints ::1:8443

Applied. The warning now writes the authority through a small package-private helper, formatAuthority(host, port). A host that contains : (after normalizeHost, only an IPv6 literal) is put back in square brackets, so the warning logs [::1]:8443; any other host is written as host:port. Only the log text changes: isAllowedAuthority and authorityMatches are untouched.

The new test theWarningNamesTheAuthorityAsAnAllowListEntry in AS2AsynchronousMDNManagerDeliveryAddressTest checks both forms. It also checks that each printed entry, once listed in asyncMdnAllowedHosts, matches the authority it was written for. Without the brackets it fails with expected: <[::1]:8443> but was: <::1:8443>. It tests the helper rather than the log line: reaching the warning needs a live connection, and for the IPv6 case a listener on ::1, which not every CI host has.

Tests (local, JDK 21): camel-as2-api 119 tests; camel-as2-component 45 unit tests (1 manual test skipped) and 112 integration tests in 11 classes; no failures. The full reactor (clean install -DskipTests -DskipITs) passes, and the files it regenerated (both as2.json copies, the Endpoint DSL and the catalog copy of as2-component.adoc) are in the commit.

Claude Code on behalf of oscerd

@oscerd
oscerd requested a review from davsclaus October 28, 2026 18:47

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Following up on my earlier review — all previous findings are now addressed.

The last remaining issue — the catalog JSON and endpoint DSL describing IPv6 allow-list entries with {code ::1} / {code ::1:8443} (brackets stripped by codegen, giving operators a silently-broken example to copy) — is fixed in this commit by switching to prose in the source Javadoc: "an IPv6 literal is written in square brackets, as in a URL". The generated artifacts now carry correct, readable descriptions. The new as2-component.adoc section includes the concrete [::1] and [::1]:8443 forms directly, which survive adoc rendering correctly.

Additionally, the new formatAuthority(host, int) method ensures the WARN log names an asyncMdnAllowedHosts entry the operator can copy verbatim: an IPv6 host is bracketed back ([::1]:8443), making the entry well-formed in both the log message and the allow-list. The roundtrip test theWarningNamesTheAuthorityAsAnAllowListEntry verifies the format→match cycle for both regular and IPv6 authorities. LGTM.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the changes since my last review: the points I raised are addressed, and CI is green on the current head.

Reviewed with Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

@davsclaus davsclaus added this to the 4.24.0 milestone Oct 29, 2026
@davsclaus davsclaus added the enhancement New feature or request label Oct 29, 2026
@davsclaus
davsclaus merged commit 8cedca3 into apache:main Oct 29, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants