diff --git a/meshchatx/src/backend/data/community_interfaces.json b/meshchatx/src/backend/data/community_interfaces.json index d952b636..eee63b7e 100644 --- a/meshchatx/src/backend/data/community_interfaces.json +++ b/meshchatx/src/backend/data/community_interfaces.json @@ -1,249 +1,239 @@ { - "_comment": "build_community_interfaces_json.py; source: directory.rns.recipes online listings. RNode omitted. Backbone without transport_identity -> TCPClientInterface. Optional override: public/community_interfaces.json.", - "_source": "https://directory.rns.recipes/api/directory/submitted?search=&type=&status=online", - "interfaces": [ - { - "name": "CRN IPv4 / IPv6", - "type": "TCPClientInterface", - "target_host": "rns.noderage.org", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "Ether Whisperer", - "type": "TCPClientInterface", - "target_host": "132.145.75.143", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "Ether Whisperer London", - "type": "TCPClientInterface", - "target_host": "132.145.75.143", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "GhostMesh TX", - "type": "TCPClientInterface", - "target_host": "rns.ghostmesh.net", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "MichMesh", - "type": "TCPClientInterface", - "target_host": "rns.michmesh.net", - "target_port": 7822, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "R-Net TCP", - "type": "TCPClientInterface", - "target_host": "istanbul.reserve.network", - "target_port": 9034, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RETICULUM WORLD", - "type": "TCPClientInterface", - "target_host": "world.reticulum.is", - "target_port": 3400, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RMAP", - "type": "TCPClientInterface", - "target_host": "rmap.world", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RNS TCP Node Germany 002", - "type": "TCPClientInterface", - "target_host": "193.26.158.230", - "target_port": 4965, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RNS Testnet BetweenTheBorders", - "type": "TCPClientInterface", - "target_host": "reticulum.betweentheborders.com", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RNS Testnet StoppedCold", - "type": "TCPClientInterface", - "target_host": "rns.stoppedcold.com", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RNS Wiegand", - "type": "TCPClientInterface", - "target_host": "rns.wiegandtech.net", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RNS at chadobear.world", - "type": "TCPClientInterface", - "target_host": "rns.chadobear.world", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RNS_Transport_US-East", - "type": "TCPClientInterface", - "target_host": "45.77.109.86", - "target_port": 4965, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "SPAGOnet", - "type": "TCPClientInterface", - "target_host": "rns.pawgslayers.club", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "SparkN0de", - "type": "TCPClientInterface", - "target_host": "aspark.uber.space", - "target_port": 44860, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "Sydney RNS", - "type": "TCPClientInterface", - "target_host": "sydney.reticulum.au", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "bnZ-NODE01 (Gothenburg SE)", - "type": "TCPClientInterface", - "target_host": "91.207.113.250", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "bnZ-RET01 (Gothenburg SE)", - "type": "TCPClientInterface", - "target_host": "213.89.12.80", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "dismails TCP Interface", - "type": "TCPClientInterface", - "target_host": "rns.dismail.de", - "target_port": 7822, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "g00n.cloud Hub", - "type": "TCPClientInterface", - "target_host": "dfw.us.g00n.cloud", - "target_port": 6969, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "mobilefabrik TCP", - "type": "TCPClientInterface", - "target_host": "phantom.mobilefabrik.com", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "reticulum.hardenedbsd.org", - "type": "TCPClientInterface", - "target_host": "reticulum.hardenedbsd.org", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "rns.noderage.org (IPv4 / IPv6)", - "type": "TCPClientInterface", - "target_host": "rns.noderage.org", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "www.vanheusden.com", - "type": "TCPClientInterface", - "target_host": "vps001.vanheusden.com", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "Beleth RNS Hub - Yggdrasil", - "type": "TCPClientInterface", - "target_host": "202:c6ff:5e33:94ca:512f:b192:36f3:1045", - "target_port": 4343, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "Spaceman-ygg", - "type": "TCPClientInterface", - "target_host": "201:e73a:61ee:ca68:4bc5:99d5:fd70:ded1", - "target_port": 4343, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "Triplebit_Minneapolis_B-Yggdrasil", - "type": "TCPClientInterface", - "target_host": "201:1160:3f65:28ea:22b2:efb:a3c0:e012", - "target_port": 9055, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "rothbard_RNS_transport_ZA_ygg", - "type": "TCPClientInterface", - "target_host": "200:73eb:2e4:14be:aac7:90b3:784b:71a3", - "target_port": 4242, - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "Casbah I2P Relay", - "type": "I2PInterface", - "i2p_peers": [ - "nckymqd5qchedbvjqsrlovgwc5iupasu3jjnt7fwws5vd4l552yq.b32.i2p" - ], - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "RNS Oren I2P", - "type": "I2PInterface", - "i2p_peers": [ - "q6qth2xl5fisekhvm2lbplprwaof4plkbh4cthjnlj2pck7ahp5q.b32.i2p" - ], - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "SparkN0de I2P", - "type": "I2PInterface", - "i2p_peers": [ - "ccrlk4gdxkgrqr633b4msujteaf7gnqw5akxjiek5dhoosfmrdka.b32.i2p" - ], - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "akku i2p", - "type": "I2PInterface", - "i2p_peers": [ - "j4qvsmifjuq2fqn4wj34xu7swgqjyror4hx3qgl3aj3ggxmg6hrq.b32.i2p" - ], - "description": "directory.rns.recipes (user-submitted, online)" - }, - { - "name": "rothbard_RNS_transport_ZA_i2p", - "type": "I2PInterface", - "i2p_peers": [ - "guuahj7pyb6ksmjv2bqrjg4cs2wou6cor3ivsi6crntqbzsxnbna.b32.i2p" - ], - "description": "directory.rns.recipes (user-submitted, online)" - } - ] + "_comment": "build_community_interfaces_json.py; source: directory.rns.recipes online listings. RNode omitted. Backbone without transport_identity -> TCPClientInterface. Optional override: public/community_interfaces.json.", + "_source": "https://directory.rns.recipes/api/directory/submitted?search=&type=&status=online", + "interfaces": [ + { + "name": "CRN IPv4 / IPv6", + "type": "TCPClientInterface", + "target_host": "rns.noderage.org", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "Ether Whisperer", + "type": "TCPClientInterface", + "target_host": "132.145.75.143", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "Ether Whisperer London", + "type": "TCPClientInterface", + "target_host": "132.145.75.143", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "GhostMesh TX", + "type": "TCPClientInterface", + "target_host": "rns.ghostmesh.net", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "MichMesh", + "type": "TCPClientInterface", + "target_host": "rns.michmesh.net", + "target_port": 7822, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "R-Net TCP", + "type": "TCPClientInterface", + "target_host": "istanbul.reserve.network", + "target_port": 9034, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RETICULUM WORLD", + "type": "TCPClientInterface", + "target_host": "world.reticulum.is", + "target_port": 3400, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RMAP", + "type": "TCPClientInterface", + "target_host": "rmap.world", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RNS TCP Node Germany 002", + "type": "TCPClientInterface", + "target_host": "193.26.158.230", + "target_port": 4965, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RNS Testnet BetweenTheBorders", + "type": "TCPClientInterface", + "target_host": "reticulum.betweentheborders.com", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RNS Testnet StoppedCold", + "type": "TCPClientInterface", + "target_host": "rns.stoppedcold.com", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RNS Wiegand", + "type": "TCPClientInterface", + "target_host": "rns.wiegandtech.net", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RNS at chadobear.world", + "type": "TCPClientInterface", + "target_host": "rns.chadobear.world", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RNS_Transport_US-East", + "type": "TCPClientInterface", + "target_host": "45.77.109.86", + "target_port": 4965, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "SPAGOnet", + "type": "TCPClientInterface", + "target_host": "rns.pawgslayers.club", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "SparkN0de", + "type": "TCPClientInterface", + "target_host": "aspark.uber.space", + "target_port": 44860, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "Sydney RNS", + "type": "TCPClientInterface", + "target_host": "sydney.reticulum.au", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "bnZ-NODE01 (Gothenburg SE)", + "type": "TCPClientInterface", + "target_host": "91.207.113.250", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "bnZ-RET01 (Gothenburg SE)", + "type": "TCPClientInterface", + "target_host": "213.89.12.80", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "dismails TCP Interface", + "type": "TCPClientInterface", + "target_host": "rns.dismail.de", + "target_port": 7822, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "g00n.cloud Hub", + "type": "TCPClientInterface", + "target_host": "dfw.us.g00n.cloud", + "target_port": 6969, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "mobilefabrik TCP", + "type": "TCPClientInterface", + "target_host": "phantom.mobilefabrik.com", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "reticulum.hardenedbsd.org", + "type": "TCPClientInterface", + "target_host": "reticulum.hardenedbsd.org", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "rns.noderage.org (IPv4 / IPv6)", + "type": "TCPClientInterface", + "target_host": "rns.noderage.org", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "www.vanheusden.com", + "type": "TCPClientInterface", + "target_host": "vps001.vanheusden.com", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "Beleth RNS Hub - Yggdrasil", + "type": "TCPClientInterface", + "target_host": "202:c6ff:5e33:94ca:512f:b192:36f3:1045", + "target_port": 4343, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "Spaceman-ygg", + "type": "TCPClientInterface", + "target_host": "201:e73a:61ee:ca68:4bc5:99d5:fd70:ded1", + "target_port": 4343, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "Triplebit_Minneapolis_B-Yggdrasil", + "type": "TCPClientInterface", + "target_host": "201:1160:3f65:28ea:22b2:efb:a3c0:e012", + "target_port": 9055, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "rothbard_RNS_transport_ZA_ygg", + "type": "TCPClientInterface", + "target_host": "200:73eb:2e4:14be:aac7:90b3:784b:71a3", + "target_port": 4242, + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "Casbah I2P Relay", + "type": "I2PInterface", + "i2p_peers": ["nckymqd5qchedbvjqsrlovgwc5iupasu3jjnt7fwws5vd4l552yq.b32.i2p"], + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "RNS Oren I2P", + "type": "I2PInterface", + "i2p_peers": ["q6qth2xl5fisekhvm2lbplprwaof4plkbh4cthjnlj2pck7ahp5q.b32.i2p"], + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "SparkN0de I2P", + "type": "I2PInterface", + "i2p_peers": ["ccrlk4gdxkgrqr633b4msujteaf7gnqw5akxjiek5dhoosfmrdka.b32.i2p"], + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "akku i2p", + "type": "I2PInterface", + "i2p_peers": ["j4qvsmifjuq2fqn4wj34xu7swgqjyror4hx3qgl3aj3ggxmg6hrq.b32.i2p"], + "description": "directory.rns.recipes (user-submitted, online)" + }, + { + "name": "rothbard_RNS_transport_ZA_i2p", + "type": "I2PInterface", + "i2p_peers": ["guuahj7pyb6ksmjv2bqrjg4cs2wou6cor3ivsi6crntqbzsxnbna.b32.i2p"], + "description": "directory.rns.recipes (user-submitted, online)" + } + ] } diff --git a/scripts/ci/slsa-predicate.py b/scripts/ci/slsa-predicate.py index 9ae3e51d..ef1fe649 100644 --- a/scripts/ci/slsa-predicate.py +++ b/scripts/ci/slsa-predicate.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Emit a SLSA v1 provenance predicate JSON on stdout (stdin unused).""" + from __future__ import annotations import json @@ -8,8 +9,12 @@ from datetime import datetime, timezone def _source_uri() -> str: - server = (os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "").rstrip("/") - repo = os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or "" + server = ( + os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "" + ).rstrip("/") + repo = ( + os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or "" + ) if not server or not repo: return "" if server.startswith("https://") or server.startswith("http://"): @@ -21,8 +26,12 @@ def _build_type() -> str: custom = os.environ.get("PROVENANCE_BUILD_TYPE") if custom: return custom - server = (os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "").rstrip("/") - repo = os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or "" + server = ( + os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "" + ).rstrip("/") + repo = ( + os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or "" + ) if server and repo: return f"{server}/{repo}/.gitea/workflows/build.yml" return "https://slsa.dev/provenance/v1" @@ -32,7 +41,9 @@ def _builder_id() -> str: custom = os.environ.get("PROVENANCE_BUILDER_ID") if custom: return custom - server = (os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "").rstrip("/") + server = ( + os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "" + ).rstrip("/") if server: return f"{server}/actions" return "https://gitea.io/actions/runner" diff --git a/tests/backend/fixtures/http_api_routes.json b/tests/backend/fixtures/http_api_routes.json index 089a5114..32e1de73 100644 --- a/tests/backend/fixtures/http_api_routes.json +++ b/tests/backend/fixtures/http_api_routes.json @@ -1,900 +1,900 @@ { - "routes": [ - { - "method": "GET", - "path": "/" - }, - { - "method": "GET", - "path": "/api/v1/announce" - }, - { - "method": "GET", - "path": "/api/v1/announces" - }, - { - "method": "GET", - "path": "/api/v1/app/changelog" - }, - { - "method": "POST", - "path": "/api/v1/app/changelog/seen" - }, - { - "method": "GET", - "path": "/api/v1/app/info" - }, - { - "method": "POST", - "path": "/api/v1/app/integrity/acknowledge" - }, - { - "method": "POST", - "path": "/api/v1/app/shutdown" - }, - { - "method": "POST", - "path": "/api/v1/app/tutorial/seen" - }, - { - "method": "POST", - "path": "/api/v1/auth/login" - }, - { - "method": "POST", - "path": "/api/v1/auth/logout" - }, - { - "method": "POST", - "path": "/api/v1/auth/setup" - }, - { - "method": "GET", - "path": "/api/v1/auth/status" - }, - { - "method": "GET", - "path": "/api/v1/blocked-destinations" - }, - { - "method": "POST", - "path": "/api/v1/blocked-destinations" - }, - { - "method": "DELETE", - "path": "/api/v1/blocked-destinations/{destination_hash}" - }, - { - "method": "POST", - "path": "/api/v1/bots/delete" - }, - { - "method": "GET", - "path": "/api/v1/bots/export" - }, - { - "method": "POST", - "path": "/api/v1/bots/restart" - }, - { - "method": "POST", - "path": "/api/v1/bots/start" - }, - { - "method": "GET", - "path": "/api/v1/bots/status" - }, - { - "method": "POST", - "path": "/api/v1/bots/stop" - }, - { - "method": "GET", - "path": "/api/v1/community-interfaces" - }, - { - "method": "GET", - "path": "/api/v1/comports" - }, - { - "method": "GET", - "path": "/api/v1/config" - }, - { - "method": "PATCH", - "path": "/api/v1/config" - }, - { - "method": "POST", - "path": "/api/v1/database/backup" - }, - { - "method": "GET", - "path": "/api/v1/database/backup/download" - }, - { - "method": "GET", - "path": "/api/v1/database/backups" - }, - { - "method": "DELETE", - "path": "/api/v1/database/backups/{filename}" - }, - { - "method": "GET", - "path": "/api/v1/database/backups/{filename}/download" - }, - { - "method": "GET", - "path": "/api/v1/database/health" - }, - { - "method": "POST", - "path": "/api/v1/database/recover" - }, - { - "method": "POST", - "path": "/api/v1/database/restore" - }, - { - "method": "POST", - "path": "/api/v1/database/restore" - }, - { - "method": "POST", - "path": "/api/v1/database/snapshot" - }, - { - "method": "GET", - "path": "/api/v1/database/snapshots" - }, - { - "method": "DELETE", - "path": "/api/v1/database/snapshots/{filename}" - }, - { - "method": "GET", - "path": "/api/v1/database/snapshots/{filename}/download" - }, - { - "method": "POST", - "path": "/api/v1/database/vacuum" - }, - { - "method": "GET", - "path": "/api/v1/debug/logs" - }, - { - "method": "GET", - "path": "/api/v1/destination/{destination_hash}/custom-display-name" - }, - { - "method": "POST", - "path": "/api/v1/destination/{destination_hash}/custom-display-name/update" - }, - { - "method": "POST", - "path": "/api/v1/destination/{destination_hash}/drop-path" - }, - { - "method": "GET", - "path": "/api/v1/destination/{destination_hash}/lxmf-stamp-info" - }, - { - "method": "GET", - "path": "/api/v1/destination/{destination_hash}/path" - }, - { - "method": "GET", - "path": "/api/v1/destination/{destination_hash}/signal-metrics" - }, - { - "method": "GET", - "path": "/api/v1/docs/export" - }, - { - "method": "GET", - "path": "/api/v1/docs/search" - }, - { - "method": "GET", - "path": "/api/v1/docs/status" - }, - { - "method": "POST", - "path": "/api/v1/docs/switch" - }, - { - "method": "POST", - "path": "/api/v1/docs/update" - }, - { - "method": "POST", - "path": "/api/v1/docs/upload" - }, - { - "method": "DELETE", - "path": "/api/v1/docs/version/{version}" - }, - { - "method": "GET", - "path": "/api/v1/favourites" - }, - { - "method": "POST", - "path": "/api/v1/favourites/add" - }, - { - "method": "DELETE", - "path": "/api/v1/favourites/{destination_hash}" - }, - { - "method": "POST", - "path": "/api/v1/favourites/{destination_hash}/rename" - }, - { - "method": "GET", - "path": "/api/v1/identities" - }, - { - "method": "POST", - "path": "/api/v1/identities/create" - }, - { - "method": "GET", - "path": "/api/v1/identities/export-all" - }, - { - "method": "POST", - "path": "/api/v1/identities/switch" - }, - { - "method": "DELETE", - "path": "/api/v1/identities/{identity_hash}" - }, - { - "method": "GET", - "path": "/api/v1/identity/backup/base32" - }, - { - "method": "GET", - "path": "/api/v1/identity/backup/download" - }, - { - "method": "POST", - "path": "/api/v1/identity/restore" - }, - { - "method": "GET", - "path": "/api/v1/interface-stats" - }, - { - "method": "GET", - "path": "/api/v1/lxmf-messages/attachment/{message_hash}/{attachment_type}" - }, - { - "method": "DELETE", - "path": "/api/v1/lxmf-messages/conversation/{destination_hash}" - }, - { - "method": "GET", - "path": "/api/v1/lxmf-messages/conversation/{destination_hash}" - }, - { - "method": "POST", - "path": "/api/v1/lxmf-messages/send" - }, - { - "method": "DELETE", - "path": "/api/v1/lxmf-messages/{hash}" - }, - { - "method": "POST", - "path": "/api/v1/lxmf-messages/{hash}/cancel" - }, - { - "method": "POST", - "path": "/api/v1/lxmf-messages/{hash}/spam" - }, - { - "method": "GET", - "path": "/api/v1/lxmf-messages/{message_hash}/uri" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/conversations" - }, - { - "method": "POST", - "path": "/api/v1/lxmf/conversations/bulk-delete" - }, - { - "method": "POST", - "path": "/api/v1/lxmf/conversations/bulk-mark-as-read" - }, - { - "method": "POST", - "path": "/api/v1/lxmf/conversations/move-to-folder" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/conversations/{destination_hash}/mark-as-read" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/folders" - }, - { - "method": "POST", - "path": "/api/v1/lxmf/folders" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/folders/export" - }, - { - "method": "POST", - "path": "/api/v1/lxmf/folders/import" - }, - { - "method": "DELETE", - "path": "/api/v1/lxmf/folders/{id}" - }, - { - "method": "PATCH", - "path": "/api/v1/lxmf/folders/{id}" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/propagation-node/status" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/propagation-node/stop-sync" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/propagation-node/sync" - }, - { - "method": "GET", - "path": "/api/v1/lxmf/propagation-nodes" - }, - { - "method": "DELETE", - "path": "/api/v1/maintenance/announces" - }, - { - "method": "DELETE", - "path": "/api/v1/maintenance/archives" - }, - { - "method": "DELETE", - "path": "/api/v1/maintenance/docs/reticulum" - }, - { - "method": "DELETE", - "path": "/api/v1/maintenance/favourites" - }, - { - "method": "DELETE", - "path": "/api/v1/maintenance/lxmf-icons" - }, - { - "method": "DELETE", - "path": "/api/v1/maintenance/messages" - }, - { - "method": "GET", - "path": "/api/v1/maintenance/messages/export" - }, - { - "method": "POST", - "path": "/api/v1/maintenance/messages/import" - }, - { - "method": "GET", - "path": "/api/v1/map/drawings" - }, - { - "method": "POST", - "path": "/api/v1/map/drawings" - }, - { - "method": "DELETE", - "path": "/api/v1/map/drawings/{drawing_id}" - }, - { - "method": "PATCH", - "path": "/api/v1/map/drawings/{drawing_id}" - }, - { - "method": "POST", - "path": "/api/v1/map/export" - }, - { - "method": "DELETE", - "path": "/api/v1/map/export/{export_id}" - }, - { - "method": "GET", - "path": "/api/v1/map/export/{export_id}" - }, - { - "method": "GET", - "path": "/api/v1/map/export/{export_id}/download" - }, - { - "method": "GET", - "path": "/api/v1/map/mbtiles" - }, - { - "method": "POST", - "path": "/api/v1/map/mbtiles/active" - }, - { - "method": "DELETE", - "path": "/api/v1/map/mbtiles/{filename}" - }, - { - "method": "GET", - "path": "/api/v1/map/offline" - }, - { - "method": "POST", - "path": "/api/v1/map/offline" - }, - { - "method": "GET", - "path": "/api/v1/map/tiles/{z}/{x}/{y}" - }, - { - "method": "GET", - "path": "/api/v1/meshchatx-docs/content" - }, - { - "method": "GET", - "path": "/api/v1/meshchatx-docs/list" - }, - { - "method": "DELETE", - "path": "/api/v1/nomadnet/archives" - }, - { - "method": "GET", - "path": "/api/v1/nomadnet/archives" - }, - { - "method": "POST", - "path": "/api/v1/nomadnetwork/{destination_hash}/identify" - }, - { - "method": "GET", - "path": "/api/v1/notifications" - }, - { - "method": "POST", - "path": "/api/v1/notifications/mark-as-viewed" - }, - { - "method": "GET", - "path": "/api/v1/page-nodes" - }, - { - "method": "POST", - "path": "/api/v1/page-nodes" - }, - { - "method": "DELETE", - "path": "/api/v1/page-nodes/{node_id}" - }, - { - "method": "GET", - "path": "/api/v1/page-nodes/{node_id}" - }, - { - "method": "POST", - "path": "/api/v1/page-nodes/{node_id}/announce" - }, - { - "method": "GET", - "path": "/api/v1/page-nodes/{node_id}/files" - }, - { - "method": "POST", - "path": "/api/v1/page-nodes/{node_id}/files" - }, - { - "method": "DELETE", - "path": "/api/v1/page-nodes/{node_id}/files/{file_name}" - }, - { - "method": "GET", - "path": "/api/v1/page-nodes/{node_id}/pages" - }, - { - "method": "POST", - "path": "/api/v1/page-nodes/{node_id}/pages" - }, - { - "method": "DELETE", - "path": "/api/v1/page-nodes/{node_id}/pages/{page_name}" - }, - { - "method": "GET", - "path": "/api/v1/page-nodes/{node_id}/pages/{page_name}" - }, - { - "method": "PUT", - "path": "/api/v1/page-nodes/{node_id}/rename" - }, - { - "method": "POST", - "path": "/api/v1/page-nodes/{node_id}/start" - }, - { - "method": "POST", - "path": "/api/v1/page-nodes/{node_id}/stop" - }, - { - "method": "GET", - "path": "/api/v1/path-table" - }, - { - "method": "POST", - "path": "/api/v1/path-table" - }, - { - "method": "GET", - "path": "/api/v1/ping/{destination_hash}/lxmf.delivery" - }, - { - "method": "GET", - "path": "/api/v1/reticulum/blackhole" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/disable-transport" - }, - { - "method": "GET", - "path": "/api/v1/reticulum/discovered-interfaces" - }, - { - "method": "GET", - "path": "/api/v1/reticulum/discovery" - }, - { - "method": "PATCH", - "path": "/api/v1/reticulum/discovery" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/enable-transport" - }, - { - "method": "GET", - "path": "/api/v1/reticulum/interfaces" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/interfaces/add" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/interfaces/delete" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/interfaces/disable" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/interfaces/enable" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/interfaces/export" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/interfaces/import" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/interfaces/import-preview" - }, - { - "method": "POST", - "path": "/api/v1/reticulum/reload" - }, - { - "method": "POST", - "path": "/api/v1/rncp/fetch" - }, - { - "method": "POST", - "path": "/api/v1/rncp/listen" - }, - { - "method": "POST", - "path": "/api/v1/rncp/send" - }, - { - "method": "GET", - "path": "/api/v1/rncp/transfer/{transfer_id}" - }, - { - "method": "POST", - "path": "/api/v1/rnpath/drop" - }, - { - "method": "POST", - "path": "/api/v1/rnpath/drop-queues" - }, - { - "method": "POST", - "path": "/api/v1/rnpath/drop-via" - }, - { - "method": "GET", - "path": "/api/v1/rnpath/rates" - }, - { - "method": "POST", - "path": "/api/v1/rnpath/request" - }, - { - "method": "GET", - "path": "/api/v1/rnpath/table" - }, - { - "method": "GET", - "path": "/api/v1/rnpath/trace/{destination_hash}" - }, - { - "method": "POST", - "path": "/api/v1/rnprobe" - }, - { - "method": "GET", - "path": "/api/v1/rnstatus" - }, - { - "method": "GET", - "path": "/api/v1/spam-keywords" - }, - { - "method": "POST", - "path": "/api/v1/spam-keywords" - }, - { - "method": "DELETE", - "path": "/api/v1/spam-keywords/{keyword_id}" - }, - { - "method": "GET", - "path": "/api/v1/status" - }, - { - "method": "GET", - "path": "/api/v1/telemetry/history/{destination_hash}" - }, - { - "method": "GET", - "path": "/api/v1/telemetry/latest/{destination_hash}" - }, - { - "method": "GET", - "path": "/api/v1/telemetry/peers" - }, - { - "method": "GET", - "path": "/api/v1/telemetry/tracking" - }, - { - "method": "POST", - "path": "/api/v1/telemetry/tracking/{destination_hash}/toggle" - }, - { - "method": "GET", - "path": "/api/v1/telemetry/trusted-peers" - }, - { - "method": "GET", - "path": "/api/v1/telephone/answer" - }, - { - "method": "GET", - "path": "/api/v1/telephone/audio-profiles" - }, - { - "method": "GET", - "path": "/api/v1/telephone/call/{identity_hash}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/contacts" - }, - { - "method": "POST", - "path": "/api/v1/telephone/contacts" - }, - { - "method": "GET", - "path": "/api/v1/telephone/contacts/check/{identity_hash}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/contacts/export" - }, - { - "method": "POST", - "path": "/api/v1/telephone/contacts/import" - }, - { - "method": "DELETE", - "path": "/api/v1/telephone/contacts/{id}" - }, - { - "method": "PATCH", - "path": "/api/v1/telephone/contacts/{id}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/hangup" - }, - { - "method": "DELETE", - "path": "/api/v1/telephone/history" - }, - { - "method": "GET", - "path": "/api/v1/telephone/history" - }, - { - "method": "GET", - "path": "/api/v1/telephone/mute-receive" - }, - { - "method": "GET", - "path": "/api/v1/telephone/mute-transmit" - }, - { - "method": "GET", - "path": "/api/v1/telephone/recordings" - }, - { - "method": "DELETE", - "path": "/api/v1/telephone/recordings/{id}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/recordings/{id}/audio/{side}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/ringtones" - }, - { - "method": "GET", - "path": "/api/v1/telephone/ringtones/status" - }, - { - "method": "POST", - "path": "/api/v1/telephone/ringtones/upload" - }, - { - "method": "DELETE", - "path": "/api/v1/telephone/ringtones/{id}" - }, - { - "method": "PATCH", - "path": "/api/v1/telephone/ringtones/{id}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/ringtones/{id}/audio" - }, - { - "method": "GET", - "path": "/api/v1/telephone/send-to-voicemail" - }, - { - "method": "GET", - "path": "/api/v1/telephone/status" - }, - { - "method": "GET", - "path": "/api/v1/telephone/switch-audio-profile/{profile_id}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/unmute-receive" - }, - { - "method": "GET", - "path": "/api/v1/telephone/unmute-transmit" - }, - { - "method": "POST", - "path": "/api/v1/telephone/voicemail/generate-greeting" - }, - { - "method": "DELETE", - "path": "/api/v1/telephone/voicemail/greeting" - }, - { - "method": "GET", - "path": "/api/v1/telephone/voicemail/greeting/audio" - }, - { - "method": "POST", - "path": "/api/v1/telephone/voicemail/greeting/record/start" - }, - { - "method": "POST", - "path": "/api/v1/telephone/voicemail/greeting/record/stop" - }, - { - "method": "POST", - "path": "/api/v1/telephone/voicemail/greeting/upload" - }, - { - "method": "GET", - "path": "/api/v1/telephone/voicemail/status" - }, - { - "method": "GET", - "path": "/api/v1/telephone/voicemails" - }, - { - "method": "DELETE", - "path": "/api/v1/telephone/voicemails/{id}" - }, - { - "method": "GET", - "path": "/api/v1/telephone/voicemails/{id}/audio" - }, - { - "method": "POST", - "path": "/api/v1/telephone/voicemails/{id}/read" - }, - { - "method": "GET", - "path": "/api/v1/tools/rnode/download_firmware" - }, - { - "method": "POST", - "path": "/api/v1/translator/install-languages" - }, - { - "method": "GET", - "path": "/api/v1/translator/languages" - }, - { - "method": "POST", - "path": "/api/v1/translator/translate" - }, - { - "method": "GET", - "path": "/call.html" - }, - { - "method": "GET", - "path": "/manifest.json" - }, - { - "method": "GET", - "path": "/service-worker.js" - }, - { - "method": "GET", - "path": "/ws" - }, - { - "method": "GET", - "path": "/ws/telephone/audio" - } - ] + "routes": [ + { + "method": "GET", + "path": "/" + }, + { + "method": "GET", + "path": "/api/v1/announce" + }, + { + "method": "GET", + "path": "/api/v1/announces" + }, + { + "method": "GET", + "path": "/api/v1/app/changelog" + }, + { + "method": "POST", + "path": "/api/v1/app/changelog/seen" + }, + { + "method": "GET", + "path": "/api/v1/app/info" + }, + { + "method": "POST", + "path": "/api/v1/app/integrity/acknowledge" + }, + { + "method": "POST", + "path": "/api/v1/app/shutdown" + }, + { + "method": "POST", + "path": "/api/v1/app/tutorial/seen" + }, + { + "method": "POST", + "path": "/api/v1/auth/login" + }, + { + "method": "POST", + "path": "/api/v1/auth/logout" + }, + { + "method": "POST", + "path": "/api/v1/auth/setup" + }, + { + "method": "GET", + "path": "/api/v1/auth/status" + }, + { + "method": "GET", + "path": "/api/v1/blocked-destinations" + }, + { + "method": "POST", + "path": "/api/v1/blocked-destinations" + }, + { + "method": "DELETE", + "path": "/api/v1/blocked-destinations/{destination_hash}" + }, + { + "method": "POST", + "path": "/api/v1/bots/delete" + }, + { + "method": "GET", + "path": "/api/v1/bots/export" + }, + { + "method": "POST", + "path": "/api/v1/bots/restart" + }, + { + "method": "POST", + "path": "/api/v1/bots/start" + }, + { + "method": "GET", + "path": "/api/v1/bots/status" + }, + { + "method": "POST", + "path": "/api/v1/bots/stop" + }, + { + "method": "GET", + "path": "/api/v1/community-interfaces" + }, + { + "method": "GET", + "path": "/api/v1/comports" + }, + { + "method": "GET", + "path": "/api/v1/config" + }, + { + "method": "PATCH", + "path": "/api/v1/config" + }, + { + "method": "POST", + "path": "/api/v1/database/backup" + }, + { + "method": "GET", + "path": "/api/v1/database/backup/download" + }, + { + "method": "GET", + "path": "/api/v1/database/backups" + }, + { + "method": "DELETE", + "path": "/api/v1/database/backups/{filename}" + }, + { + "method": "GET", + "path": "/api/v1/database/backups/{filename}/download" + }, + { + "method": "GET", + "path": "/api/v1/database/health" + }, + { + "method": "POST", + "path": "/api/v1/database/recover" + }, + { + "method": "POST", + "path": "/api/v1/database/restore" + }, + { + "method": "POST", + "path": "/api/v1/database/restore" + }, + { + "method": "POST", + "path": "/api/v1/database/snapshot" + }, + { + "method": "GET", + "path": "/api/v1/database/snapshots" + }, + { + "method": "DELETE", + "path": "/api/v1/database/snapshots/{filename}" + }, + { + "method": "GET", + "path": "/api/v1/database/snapshots/{filename}/download" + }, + { + "method": "POST", + "path": "/api/v1/database/vacuum" + }, + { + "method": "GET", + "path": "/api/v1/debug/logs" + }, + { + "method": "GET", + "path": "/api/v1/destination/{destination_hash}/custom-display-name" + }, + { + "method": "POST", + "path": "/api/v1/destination/{destination_hash}/custom-display-name/update" + }, + { + "method": "POST", + "path": "/api/v1/destination/{destination_hash}/drop-path" + }, + { + "method": "GET", + "path": "/api/v1/destination/{destination_hash}/lxmf-stamp-info" + }, + { + "method": "GET", + "path": "/api/v1/destination/{destination_hash}/path" + }, + { + "method": "GET", + "path": "/api/v1/destination/{destination_hash}/signal-metrics" + }, + { + "method": "GET", + "path": "/api/v1/docs/export" + }, + { + "method": "GET", + "path": "/api/v1/docs/search" + }, + { + "method": "GET", + "path": "/api/v1/docs/status" + }, + { + "method": "POST", + "path": "/api/v1/docs/switch" + }, + { + "method": "POST", + "path": "/api/v1/docs/update" + }, + { + "method": "POST", + "path": "/api/v1/docs/upload" + }, + { + "method": "DELETE", + "path": "/api/v1/docs/version/{version}" + }, + { + "method": "GET", + "path": "/api/v1/favourites" + }, + { + "method": "POST", + "path": "/api/v1/favourites/add" + }, + { + "method": "DELETE", + "path": "/api/v1/favourites/{destination_hash}" + }, + { + "method": "POST", + "path": "/api/v1/favourites/{destination_hash}/rename" + }, + { + "method": "GET", + "path": "/api/v1/identities" + }, + { + "method": "POST", + "path": "/api/v1/identities/create" + }, + { + "method": "GET", + "path": "/api/v1/identities/export-all" + }, + { + "method": "POST", + "path": "/api/v1/identities/switch" + }, + { + "method": "DELETE", + "path": "/api/v1/identities/{identity_hash}" + }, + { + "method": "GET", + "path": "/api/v1/identity/backup/base32" + }, + { + "method": "GET", + "path": "/api/v1/identity/backup/download" + }, + { + "method": "POST", + "path": "/api/v1/identity/restore" + }, + { + "method": "GET", + "path": "/api/v1/interface-stats" + }, + { + "method": "GET", + "path": "/api/v1/lxmf-messages/attachment/{message_hash}/{attachment_type}" + }, + { + "method": "DELETE", + "path": "/api/v1/lxmf-messages/conversation/{destination_hash}" + }, + { + "method": "GET", + "path": "/api/v1/lxmf-messages/conversation/{destination_hash}" + }, + { + "method": "POST", + "path": "/api/v1/lxmf-messages/send" + }, + { + "method": "DELETE", + "path": "/api/v1/lxmf-messages/{hash}" + }, + { + "method": "POST", + "path": "/api/v1/lxmf-messages/{hash}/cancel" + }, + { + "method": "POST", + "path": "/api/v1/lxmf-messages/{hash}/spam" + }, + { + "method": "GET", + "path": "/api/v1/lxmf-messages/{message_hash}/uri" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/conversations" + }, + { + "method": "POST", + "path": "/api/v1/lxmf/conversations/bulk-delete" + }, + { + "method": "POST", + "path": "/api/v1/lxmf/conversations/bulk-mark-as-read" + }, + { + "method": "POST", + "path": "/api/v1/lxmf/conversations/move-to-folder" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/conversations/{destination_hash}/mark-as-read" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/folders" + }, + { + "method": "POST", + "path": "/api/v1/lxmf/folders" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/folders/export" + }, + { + "method": "POST", + "path": "/api/v1/lxmf/folders/import" + }, + { + "method": "DELETE", + "path": "/api/v1/lxmf/folders/{id}" + }, + { + "method": "PATCH", + "path": "/api/v1/lxmf/folders/{id}" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/propagation-node/status" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/propagation-node/stop-sync" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/propagation-node/sync" + }, + { + "method": "GET", + "path": "/api/v1/lxmf/propagation-nodes" + }, + { + "method": "DELETE", + "path": "/api/v1/maintenance/announces" + }, + { + "method": "DELETE", + "path": "/api/v1/maintenance/archives" + }, + { + "method": "DELETE", + "path": "/api/v1/maintenance/docs/reticulum" + }, + { + "method": "DELETE", + "path": "/api/v1/maintenance/favourites" + }, + { + "method": "DELETE", + "path": "/api/v1/maintenance/lxmf-icons" + }, + { + "method": "DELETE", + "path": "/api/v1/maintenance/messages" + }, + { + "method": "GET", + "path": "/api/v1/maintenance/messages/export" + }, + { + "method": "POST", + "path": "/api/v1/maintenance/messages/import" + }, + { + "method": "GET", + "path": "/api/v1/map/drawings" + }, + { + "method": "POST", + "path": "/api/v1/map/drawings" + }, + { + "method": "DELETE", + "path": "/api/v1/map/drawings/{drawing_id}" + }, + { + "method": "PATCH", + "path": "/api/v1/map/drawings/{drawing_id}" + }, + { + "method": "POST", + "path": "/api/v1/map/export" + }, + { + "method": "DELETE", + "path": "/api/v1/map/export/{export_id}" + }, + { + "method": "GET", + "path": "/api/v1/map/export/{export_id}" + }, + { + "method": "GET", + "path": "/api/v1/map/export/{export_id}/download" + }, + { + "method": "GET", + "path": "/api/v1/map/mbtiles" + }, + { + "method": "POST", + "path": "/api/v1/map/mbtiles/active" + }, + { + "method": "DELETE", + "path": "/api/v1/map/mbtiles/{filename}" + }, + { + "method": "GET", + "path": "/api/v1/map/offline" + }, + { + "method": "POST", + "path": "/api/v1/map/offline" + }, + { + "method": "GET", + "path": "/api/v1/map/tiles/{z}/{x}/{y}" + }, + { + "method": "GET", + "path": "/api/v1/meshchatx-docs/content" + }, + { + "method": "GET", + "path": "/api/v1/meshchatx-docs/list" + }, + { + "method": "DELETE", + "path": "/api/v1/nomadnet/archives" + }, + { + "method": "GET", + "path": "/api/v1/nomadnet/archives" + }, + { + "method": "POST", + "path": "/api/v1/nomadnetwork/{destination_hash}/identify" + }, + { + "method": "GET", + "path": "/api/v1/notifications" + }, + { + "method": "POST", + "path": "/api/v1/notifications/mark-as-viewed" + }, + { + "method": "GET", + "path": "/api/v1/page-nodes" + }, + { + "method": "POST", + "path": "/api/v1/page-nodes" + }, + { + "method": "DELETE", + "path": "/api/v1/page-nodes/{node_id}" + }, + { + "method": "GET", + "path": "/api/v1/page-nodes/{node_id}" + }, + { + "method": "POST", + "path": "/api/v1/page-nodes/{node_id}/announce" + }, + { + "method": "GET", + "path": "/api/v1/page-nodes/{node_id}/files" + }, + { + "method": "POST", + "path": "/api/v1/page-nodes/{node_id}/files" + }, + { + "method": "DELETE", + "path": "/api/v1/page-nodes/{node_id}/files/{file_name}" + }, + { + "method": "GET", + "path": "/api/v1/page-nodes/{node_id}/pages" + }, + { + "method": "POST", + "path": "/api/v1/page-nodes/{node_id}/pages" + }, + { + "method": "DELETE", + "path": "/api/v1/page-nodes/{node_id}/pages/{page_name}" + }, + { + "method": "GET", + "path": "/api/v1/page-nodes/{node_id}/pages/{page_name}" + }, + { + "method": "PUT", + "path": "/api/v1/page-nodes/{node_id}/rename" + }, + { + "method": "POST", + "path": "/api/v1/page-nodes/{node_id}/start" + }, + { + "method": "POST", + "path": "/api/v1/page-nodes/{node_id}/stop" + }, + { + "method": "GET", + "path": "/api/v1/path-table" + }, + { + "method": "POST", + "path": "/api/v1/path-table" + }, + { + "method": "GET", + "path": "/api/v1/ping/{destination_hash}/lxmf.delivery" + }, + { + "method": "GET", + "path": "/api/v1/reticulum/blackhole" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/disable-transport" + }, + { + "method": "GET", + "path": "/api/v1/reticulum/discovered-interfaces" + }, + { + "method": "GET", + "path": "/api/v1/reticulum/discovery" + }, + { + "method": "PATCH", + "path": "/api/v1/reticulum/discovery" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/enable-transport" + }, + { + "method": "GET", + "path": "/api/v1/reticulum/interfaces" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/interfaces/add" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/interfaces/delete" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/interfaces/disable" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/interfaces/enable" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/interfaces/export" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/interfaces/import" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/interfaces/import-preview" + }, + { + "method": "POST", + "path": "/api/v1/reticulum/reload" + }, + { + "method": "POST", + "path": "/api/v1/rncp/fetch" + }, + { + "method": "POST", + "path": "/api/v1/rncp/listen" + }, + { + "method": "POST", + "path": "/api/v1/rncp/send" + }, + { + "method": "GET", + "path": "/api/v1/rncp/transfer/{transfer_id}" + }, + { + "method": "POST", + "path": "/api/v1/rnpath/drop" + }, + { + "method": "POST", + "path": "/api/v1/rnpath/drop-queues" + }, + { + "method": "POST", + "path": "/api/v1/rnpath/drop-via" + }, + { + "method": "GET", + "path": "/api/v1/rnpath/rates" + }, + { + "method": "POST", + "path": "/api/v1/rnpath/request" + }, + { + "method": "GET", + "path": "/api/v1/rnpath/table" + }, + { + "method": "GET", + "path": "/api/v1/rnpath/trace/{destination_hash}" + }, + { + "method": "POST", + "path": "/api/v1/rnprobe" + }, + { + "method": "GET", + "path": "/api/v1/rnstatus" + }, + { + "method": "GET", + "path": "/api/v1/spam-keywords" + }, + { + "method": "POST", + "path": "/api/v1/spam-keywords" + }, + { + "method": "DELETE", + "path": "/api/v1/spam-keywords/{keyword_id}" + }, + { + "method": "GET", + "path": "/api/v1/status" + }, + { + "method": "GET", + "path": "/api/v1/telemetry/history/{destination_hash}" + }, + { + "method": "GET", + "path": "/api/v1/telemetry/latest/{destination_hash}" + }, + { + "method": "GET", + "path": "/api/v1/telemetry/peers" + }, + { + "method": "GET", + "path": "/api/v1/telemetry/tracking" + }, + { + "method": "POST", + "path": "/api/v1/telemetry/tracking/{destination_hash}/toggle" + }, + { + "method": "GET", + "path": "/api/v1/telemetry/trusted-peers" + }, + { + "method": "GET", + "path": "/api/v1/telephone/answer" + }, + { + "method": "GET", + "path": "/api/v1/telephone/audio-profiles" + }, + { + "method": "GET", + "path": "/api/v1/telephone/call/{identity_hash}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/contacts" + }, + { + "method": "POST", + "path": "/api/v1/telephone/contacts" + }, + { + "method": "GET", + "path": "/api/v1/telephone/contacts/check/{identity_hash}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/contacts/export" + }, + { + "method": "POST", + "path": "/api/v1/telephone/contacts/import" + }, + { + "method": "DELETE", + "path": "/api/v1/telephone/contacts/{id}" + }, + { + "method": "PATCH", + "path": "/api/v1/telephone/contacts/{id}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/hangup" + }, + { + "method": "DELETE", + "path": "/api/v1/telephone/history" + }, + { + "method": "GET", + "path": "/api/v1/telephone/history" + }, + { + "method": "GET", + "path": "/api/v1/telephone/mute-receive" + }, + { + "method": "GET", + "path": "/api/v1/telephone/mute-transmit" + }, + { + "method": "GET", + "path": "/api/v1/telephone/recordings" + }, + { + "method": "DELETE", + "path": "/api/v1/telephone/recordings/{id}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/recordings/{id}/audio/{side}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/ringtones" + }, + { + "method": "GET", + "path": "/api/v1/telephone/ringtones/status" + }, + { + "method": "POST", + "path": "/api/v1/telephone/ringtones/upload" + }, + { + "method": "DELETE", + "path": "/api/v1/telephone/ringtones/{id}" + }, + { + "method": "PATCH", + "path": "/api/v1/telephone/ringtones/{id}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/ringtones/{id}/audio" + }, + { + "method": "GET", + "path": "/api/v1/telephone/send-to-voicemail" + }, + { + "method": "GET", + "path": "/api/v1/telephone/status" + }, + { + "method": "GET", + "path": "/api/v1/telephone/switch-audio-profile/{profile_id}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/unmute-receive" + }, + { + "method": "GET", + "path": "/api/v1/telephone/unmute-transmit" + }, + { + "method": "POST", + "path": "/api/v1/telephone/voicemail/generate-greeting" + }, + { + "method": "DELETE", + "path": "/api/v1/telephone/voicemail/greeting" + }, + { + "method": "GET", + "path": "/api/v1/telephone/voicemail/greeting/audio" + }, + { + "method": "POST", + "path": "/api/v1/telephone/voicemail/greeting/record/start" + }, + { + "method": "POST", + "path": "/api/v1/telephone/voicemail/greeting/record/stop" + }, + { + "method": "POST", + "path": "/api/v1/telephone/voicemail/greeting/upload" + }, + { + "method": "GET", + "path": "/api/v1/telephone/voicemail/status" + }, + { + "method": "GET", + "path": "/api/v1/telephone/voicemails" + }, + { + "method": "DELETE", + "path": "/api/v1/telephone/voicemails/{id}" + }, + { + "method": "GET", + "path": "/api/v1/telephone/voicemails/{id}/audio" + }, + { + "method": "POST", + "path": "/api/v1/telephone/voicemails/{id}/read" + }, + { + "method": "GET", + "path": "/api/v1/tools/rnode/download_firmware" + }, + { + "method": "POST", + "path": "/api/v1/translator/install-languages" + }, + { + "method": "GET", + "path": "/api/v1/translator/languages" + }, + { + "method": "POST", + "path": "/api/v1/translator/translate" + }, + { + "method": "GET", + "path": "/call.html" + }, + { + "method": "GET", + "path": "/manifest.json" + }, + { + "method": "GET", + "path": "/service-worker.js" + }, + { + "method": "GET", + "path": "/ws" + }, + { + "method": "GET", + "path": "/ws/telephone/audio" + } + ] } diff --git a/tests/backend/test_http_api_contract.py b/tests/backend/test_http_api_contract.py index 29a74348..ad9f93fa 100644 --- a/tests/backend/test_http_api_contract.py +++ b/tests/backend/test_http_api_contract.py @@ -23,7 +23,9 @@ def test_meshchat_http_routes_match_fixture(): live = extract_meshchat_http_routes(_MESHCHAT_PY) if os.environ.get("UPDATE_HTTP_API_ROUTES") == "1": write_route_fixture(_FIXTURE, live) - pytest.skip("UPDATE_HTTP_API_ROUTES=1: fixture updated; re-run without the env var") + pytest.skip( + "UPDATE_HTTP_API_ROUTES=1: fixture updated; re-run without the env var" + ) expected = load_route_fixture(_FIXTURE) assert live == expected, ( "HTTP route list drifted. If you added or renamed routes, run: " diff --git a/tests/backend/test_reticulum_live_network.py b/tests/backend/test_reticulum_live_network.py index c952fc54..3686beca 100644 --- a/tests/backend/test_reticulum_live_network.py +++ b/tests/backend/test_reticulum_live_network.py @@ -21,7 +21,10 @@ _RUN = os.environ.get("MESHCHAT_LIVE_RETICULUM") == "1" @pytest.mark.integration -@pytest.mark.skipif(not _RUN, reason="Set MESHCHAT_LIVE_RETICULUM=1 to run live Reticulum subprocess smoke test") +@pytest.mark.skipif( + not _RUN, + reason="Set MESHCHAT_LIVE_RETICULUM=1 to run live Reticulum subprocess smoke test", +) def test_reticulum_subprocess_start_and_exit(): script = r""" import tempfile diff --git a/tests/e2e/helpers.js b/tests/e2e/helpers.js index 592f1f79..4df90cea 100644 --- a/tests/e2e/helpers.js +++ b/tests/e2e/helpers.js @@ -30,7 +30,7 @@ async function openCommandPalette(page) { ctrlKey: true, bubbles: true, cancelable: true, - }), + }) ); }); input = page.getByPlaceholder(PALETTE_PLACEHOLDER); diff --git a/tests/e2e/navigation.spec.js b/tests/e2e/navigation.spec.js index 36f5c82a..24d5ab66 100644 --- a/tests/e2e/navigation.spec.js +++ b/tests/e2e/navigation.spec.js @@ -8,9 +8,9 @@ test.describe("Getting started (tutorial page)", () => { await expect(page.getByRole("heading", { name: /Welcome to\s*MeshChatX/i }).first()).toBeVisible({ timeout: 30000, }); - await expect( - page.getByText("The future of off-grid communication", { exact: false }).first(), - ).toBeVisible({ timeout: 10000 }); + await expect(page.getByText("The future of off-grid communication", { exact: false }).first()).toBeVisible({ + timeout: 10000, + }); }); }); diff --git a/tests/frontend/Accessibility.test.js b/tests/frontend/Accessibility.test.js index f5e1b04a..f8ed5db1 100644 --- a/tests/frontend/Accessibility.test.js +++ b/tests/frontend/Accessibility.test.js @@ -23,11 +23,10 @@ describe("UI Accessibility and Keyboard Navigation", () => { it("verifies that keyboard shortcuts trigger global events", async () => { const emitSpy = vi.spyOn(GlobalEmitter, "emit"); - // Test a few shortcuts + // Test a few shortcuts (Ctrl+K is handled by CommandPalette in capture phase; KeyboardShortcuts skips emitting it) const shortcuts = [ { key: "1", altKey: true, action: "nav_messages" }, { key: "s", altKey: true, action: "nav_settings" }, - { key: "k", ctrlKey: true, action: "command_palette" }, ]; for (const shortcut of shortcuts) { @@ -41,6 +40,15 @@ describe("UI Accessibility and Keyboard Navigation", () => { window.dispatchEvent(event); expect(emitSpy).toHaveBeenCalledWith("keyboard-shortcut", shortcut.action); } + + const ctrlK = new KeyboardEvent("keydown", { + key: "k", + ctrlKey: true, + code: "KeyK", + bubbles: true, + }); + window.dispatchEvent(ctrlK); + expect(emitSpy).toHaveBeenCalledTimes(2); }); it("ensures shortcuts are ignored in inputs without modifiers", async () => {