Skip to content

MIM-2647 Entity Capabilities 2.0 (XEP-0390)#4666

Merged
chrzaszcz merged 8 commits intofeature/capsfrom
caps-v2
Mar 17, 2026
Merged

MIM-2647 Entity Capabilities 2.0 (XEP-0390)#4666
chrzaszcz merged 8 commits intofeature/capsfrom
caps-v2

Conversation

@chrzaszcz
Copy link
Copy Markdown
Member

@chrzaszcz chrzaszcz commented Mar 5, 2026

This PR adds support for XEP-0390: Entity Capabilities 2.0 while updating the support for XEP-0115.

The following mod_caps version notation is now used in the code, tests and docs:

  • v1 implements XEP-0115.
  • v2 implements XEP-0390.

Changes

  1. Add v2 support in mod_caps and mod_caps_hash, and protocol document details and deviations.
  2. Add modules.mod_caps.versions config option with docs and tests.
  3. Support more hashing algorithms from XEP-0300.
  4. Extend mod_caps_SUITE to test v1 and v2 hashing, and add tests for special cases with detailed docs.
  5. Update big tests to run with v1/v2, and add tests for corner cases.

More details in commit messages and comments/docs in the code.

Notes:

  • escalus is temporarily used from Add utilities for XEP-0115 and XEP-0390 escalus#287, and this commit needs updating after releasing the new version of escalus. This is why this PR is still a draft.
  • mongoose_data_forms could provide more validation, e.g. for duplicate fields (currently, last one wins) or for ensuring FORM_TYPE is hidden. We could think of such extensions later.

@chrzaszcz chrzaszcz changed the title Add support for caps 2.0 hashing according to XEP-0390 [WIP] Caps 2.0 XEP-0390 Mar 5, 2026
@mongoose-im
Copy link
Copy Markdown
Collaborator

mongoose-im commented Mar 5, 2026

CircleCI results for 9ffe0d4


elasticsearch_and_cassandra_latest / elasticsearch_and_cassandra_mnesia / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 672 / Failed: 0 / User-skipped: 83 / Auto-skipped: 0


small_tests_legacy / small_tests / fca7f70
Reports root / small


small_tests_latest / small_tests / fca7f70
Reports root / small


small_tests_latest_arm64 / small_tests / fca7f70
Reports root / small


ldap_mnesia_legacy / ldap_mnesia / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 2246 / Failed: 0 / User-skipped: 1446 / Auto-skipped: 0


ldap_mnesia_latest / ldap_mnesia / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 2246 / Failed: 0 / User-skipped: 1446 / Auto-skipped: 0


dynamic_domains_pgsql_mnesia_legacy / pgsql_mnesia / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 5140 / Failed: 0 / User-skipped: 209 / Auto-skipped: 0


dynamic_domains_pgsql_mnesia_latest / pgsql_mnesia / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 5140 / Failed: 0 / User-skipped: 209 / Auto-skipped: 0


dynamic_domains_mysql_redis_latest / mysql_redis / 1fdb216
Status: 🟢 Passed
Reports root/ big
OK: 5104 / Failed: 0 / User-skipped: 245 / Auto-skipped: 0


internal_mnesia_latest / internal_mnesia / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 117 / Failed: 0 / User-skipped: 2 / Auto-skipped: 0


pgsql_cets_latest / pgsql_cets / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 5274 / Failed: 0 / User-skipped: 203 / Auto-skipped: 0


pgsql_mnesia_legacy / pgsql_mnesia / 1fdb216
Status: 🟢 Passed
Reports root/ big
OK: 45 / Failed: 0 / User-skipped: 0 / Auto-skipped: 1

connect_SUITE:session_replacement:replaced_session_cannot_terminate_different_nodes
{skip,
  {failed,
    {connect_SUITE,init_per_testcase,
      {{verify_result,[],
         [{times,20,
            [{#{node => mongooseim2@localhost},
            [mongooseim@localhost],
            true},
             {#{node => mongooseim@localhost},
            [mongooseim2@localhost],
            true}]}],
         undefined},
       [{wait_helper,do_wait_until,1,
          [{file,
             "/home/circleci/project/big_tests/_build/default/lib/wait_helper/src/wait_helper.erl"},
           {line,127}]},
        {distributed_helper,verify_result,2,
          [{file,
             "/home/circleci/project/big_tests/../test/common/distributed_helper.erl"},
           {line,75}]},
        {distributed_helper,add_node_to_cluster,2,
          [{file,
             "/home/circleci/project/big_tests/../test/common/distributed_helper.erl"},
           {line,39}]},
        {connect_SUITE,init_per_testcase,2,
          [{file,
             "/home/circleci/project/big_tests/tests/connect_SUITE.erl"},
           {line,216}]},
        {test_server,do_init_per_testcase,2,
          [{file,"test_server.erl"},{line,1564}]},
        {test_server,run_test_case_eval1,6,
          [{file,"test_server.erl"},{line,1265}]},
        {test_server,run_test_case_eval,9,
          [{file,"test_server.erl"},{line,1235}]}]}}}}

Report log


cockroachdb_cets_latest / cockroachdb_cets / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 5274 / Failed: 0 / User-skipped: 203 / Auto-skipped: 0


pgsql_mnesia_latest / pgsql_mnesia / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 5457 / Failed: 0 / User-skipped: 263 / Auto-skipped: 0


mysql_redis_latest / mysql_redis / fca7f70
Status: 🟢 Passed
Reports root/ big
OK: 5450 / Failed: 0 / User-skipped: 270 / Auto-skipped: 0

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.73%. Comparing base (657dad8) to head (fca7f70).
⚠️ Report is 20 commits behind head on feature/caps.

Additional details and impacted files
@@               Coverage Diff                @@
##           feature/caps    #4666      +/-   ##
================================================
+ Coverage         85.40%   85.73%   +0.33%     
================================================
  Files               555      549       -6     
  Lines             33232    33189      -43     
================================================
+ Hits              28382    28455      +73     
+ Misses             4850     4734     -116     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Base automatically changed from caps-mvp to feature/caps March 6, 2026 14:43
@chrzaszcz chrzaszcz force-pushed the caps-v2 branch 5 times, most recently from 9a81f68 to e0f902b Compare March 13, 2026 13:51
@chrzaszcz chrzaszcz changed the title [WIP] Caps 2.0 XEP-0390 MIM-2647 Entity Capabilities 2.0 XEP-0390 Mar 13, 2026
@chrzaszcz chrzaszcz changed the title MIM-2647 Entity Capabilities 2.0 XEP-0390 MIM-2647 Entity Capabilities 2.0 (XEP-0390) Mar 13, 2026
@chrzaszcz chrzaszcz requested a review from Copilot March 13, 2026 14:39
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for XEP-0390 (Entity Capabilities 2.0) alongside existing XEP-0115 caps handling, including new hashing/encoding logic, configurable protocol versions, and updated unit/big tests.

Changes:

  • Extend mod_caps to advertise/process both caps v1 (XEP-0115) and caps v2 (XEP-0390), with versions config to control accepted/advertised versions.
  • Rework mod_caps_hash to support versioned encoding rules and additional hash algorithms (SHA3, SHAKE, BLAKE2b, etc.).
  • Update CT suites and big tests (including test data XML) to cover v1/v2 behavior and error cases; switch big-tests’ escalus dependency to a git branch.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/caps/mod_caps.erl Add v2 caps extraction/advertising, versioned server hash generation, and versioned hash verification.
src/caps/mod_caps_hash.erl Implement versioned caps encoding and broaden supported hash algorithms.
include/mongoose_ns.hrl Add namespaces for XEP-0390 caps (NS_CAPS_2) and XEP-0300 hashes (NS_HASH).
doc/modules/mod_caps.md Document XEP-0390 support and new modules.mod_caps.versions option.
test/mod_caps_SUITE.erl Expand hashing tests across v1/v2, add special-case validation tests, and refactor fixtures.
test/mod_caps_SUITE_data/simple_response.xml Adjust XML fixture root to be <query/> only.
test/mod_caps_SUITE_data/simple_response_2.xml Add XEP-0390 “simple” example fixture.
test/mod_caps_SUITE_data/complex_response.xml Adjust XML fixture root to be <query/> only and reorder elements for sorting coverage.
test/mod_caps_SUITE_data/complex_response_2.xml Add XEP-0390 “complex” example fixture.
test/config_parser_SUITE.erl Add parsing coverage for modules.mod_caps.versions and reject invalid versions.
test/config_parser_SUITE_data/modules.toml Add versions = ["v2"] example for mod_caps.
test/common/config_parser_helper.erl Extend default/all-modules mod_caps configs with versions.
big_tests/tests/pep_SUITE.erl Update caps helper calls to pass explicit caps version (v1).
big_tests/tests/disco_and_caps_SUITE.erl Split big tests into caps v1/v2 groups and add new server/client error-path scenarios.
big_tests/tests/caps_helper.erl Add caps version support for generated caps stanzas and hashing RPC.
big_tests/rebar.config Switch escalus dependency from hex version to a git branch.
big_tests/rebar.lock Remove escalus pkg lock entry (currently leaving the lock inconsistent with rebar.config).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Introduce a new 'versions' option with a list of supported versions.
  XEP-0115 becomes v1, and XEP-0390 becomes v2.
- Add the corresponding caps features to disco responses.
- Fix the issue, where a query to an invalid node would still return
  the caps namespace.
- Advertise the corresponding server capabilities in stream features.
- Consume and verify the corresponding client capabilities.
- Attempt to request caps from the client in the order of configured
  versions.
- Pass the version to the hash generating API.
- Rework encoding to implement the common part only once.
- Add detailed description and comments on all protocol details.
- Try to support both XEPs whenever possible:
    v1: becomes more strict than before, but all within XEP-0115.
    v2: in line with XEP-0390 except some cases listed in 'moduledoc'.
- Support more hashing functions. Skip ones not supported in Erlang.
- Make the check for supported algorithms more robust,
  because some hashing algorithms are not supported e.g. in older
  LibreSSL versions.
- Add examples from XEP-0390; adjust the XEP-0115 ones for consistency
- Shuffle the complex responses more thoroughly to check sorting
- Perform hashing tests for both v1 and v2
- Test all supported hashing algorithms.
- Check the corner cases for v1 and v2, and document the tested
  behaviour with sources.
- Extract reusable helpers to escalus.
- Run caps tests in disco_and_caps_SUITE for v1 and v2.
  Both versions are enabled on the server (as by default),
  and the client decides which one to use.
- Check some previously missed corner cases:
  1) Ask for the server capabilities with a malformed/incorrect node
  2) Respond to the disco#info request with invalid elements
@telezynski
Copy link
Copy Markdown
Member

Nice and clean. Just a couple of cosmetic issues, feel free to ignore.

@chrzaszcz chrzaszcz marked this pull request as ready for review March 17, 2026 13:49
@chrzaszcz chrzaszcz merged commit a05cdaf into feature/caps Mar 17, 2026
4 checks passed
@chrzaszcz chrzaszcz deleted the caps-v2 branch March 17, 2026 14:01
@chrzaszcz chrzaszcz mentioned this pull request Mar 23, 2026
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.

4 participants