Changelog
This page aggregates changelogs from all ros2_medkit packages.
Changelog for package ros2_medkit_gateway
0.6.0 (2026-06-22)
SOVD entity status and lifecycle control endpoints:
GET /apps/{id}/statusandGET /components/{id}/status, plus lifecycle control routes backed by a newLifecycleProviderplugin interface and plugin-manager routing. Control returns501 Not Implementeduntil a provider is registered; the routes are RBAC-gated, advertised via astatuslink on app and component detail, and declared under the OpenAPILifecycletag (#437)Accurate app and component status: app status is read from the managed-node lifecycle state through a
GetState-backed reader, and a component reportsnotReadywhen all hosted apps are offline while stayingreadyas long as it is reachable (#455)Bounded the executor and HTTP server thread pools, sized to the cold-wait plus SSE budget, with misconfiguration guards and a bounded keep-alive timeout (#457)
Startup discovery summary logged at boot, with an empty-graph warning when no entities are discovered (#438)
Bounded the unsupported-message-type cache and exposed its size; unknown message types now warn once instead of on every sample (#450)
OpenAPI query parameters are derived from a typed query contract, tightening the query-parameter schema and its regression gate (#417)
PluginContextcan aggregate peer faults across daisy-chained gateways through the SOVD service interface (#419)Single-command bringup of the local medkit stack via
bringup.launch.pyandbringup_params.yaml(#439)Docker image enables CORS for the documented web UI path and uses explicit web UI origins instead of wildcard CORS (#452)
Docker image bundles the CycloneDDS RMW as an opt-in alternative implementation (#451)
Native gateway launch enables web UI CORS by default and honors the CORS settings from a supplied
config_file(#461)Incremental, embedded-hardened entity cache:
ThreadSafeEntityCachestores entities in a fixed-capacitySlotStoreobject pool indexed by open-addressed flat hash maps, andupdate_allreconciles the discovery output by id (add / remove / change only) so steady-state refresh does zero structural allocations. Capacity is reserved viaentity_cache.capacity(default 256) and cache stats are exposed on/healthasx-medkit-entity-cache. Discovery refreshes are debounced viadiscovery.refresh_debounce_ms(default 1000) and operationtype_infoschemas resolve lazily, cutting gateway CPU under graph churn roughly 4x. Entity detailoperations[]no longer embeds schemas eagerly; the schemas remain on the/operationsresource (#462)Contributors: @bburda, @mfaferek93
0.5.0 (2026-06-08)
Breaking Changes:
Typed router refactor.
HandlerContextno longer carriessend_json/send_error/send_plugin_error/send_dto/parse_body: handlers returnhttp::Result<TResponse>and the framework owns response writing throughRouteRegistry. The rawvoid(httplib::Request, httplib::Response)RouteRegistrylambda overloads are removed - call sites must use the typedreg.get<T>/reg.post<TBody, T>/reg.del<T>overloads, the multi-shapereg.post_alternates<TBody, TAlt...>/reg.del_alternates<TAlt...>, or one of the named escape hatches (reg.sse/reg.binary_download/reg.multipart_upload<T>/reg.static_asset/reg.docs_endpoint/reg.docs_subtree).static_assert(dto::has_dto_shape_v<T>)gates every typed overload, so non-DTO return types fail at compile time. The plugin ABI is unaffected:PluginResponsekeeps itssend_json/send_errorsurface and now routes through the same internalhttp::detail::write_json_bodyprimitive as the framework, so plugin wire format is unchanged (#403)Provider ABI typed.
FaultProvider,DataProvider,OperationProvider, andUpdateProvider::get_updatereturn typed DTO envelopes (FaultListResult/FaultDetailResult/FaultClearResult/ the matchingData*ResultandOperation*Resultshapes /UpdateStatusResult) instead of rawtl::expected<nlohmann::json, ErrorInfo>. The wire bytes are byte-identical because each envelope wraps an opaquecontentobject emitted verbatim byJsonWriter; commercial and out-of-tree plugins must wrap their existing JSON in the matching envelope type (mechanical:Result.content = std::move(json_payload)). The plugin ABI itself (PluginRouteshape,PluginResponsector, plugin api version) is locked bytest_plugin_abi_conformanceand is unchanged (#403)SchemaWriteremits optional DTO fields asanyOf: [<inner>, {type: "null"}](the OpenAPI 3.1 idiom) instead ofnullable: true. Generated clients seeT | nullfor every optional field rather thanT | undefined. Wire format is unchanged - the gateway still omits absent optional fields, andJsonReadercontinues to accept absent fields; the schema change only opts the published spec into round-tripping a literalnullvalue cleanly for clients that prefer to send one. As part of this, a handful of fields that were previously emitted as an explicit JSONnullwhen absent are now omitted entirely (consistent with the optional-omission policy): the script execution fieldsprogress/started_at/completed_at/parameters/error(GET .../scripts/{id}/executions/{eid}) and the scriptparameters_schemafield (GET .../scripts/{id}). Clients that testedfield === nullor relied on the key always being present must treat an absent key the same asnull(#403)Synchronous operation-execution service-call failures (
POST /api/v1/{entity-path}/operations/{id}/executionswhen the underlying ROS 2 service call fails) now return the standard SOVDGenericErrorenvelope ({"error_code": "vendor-error", "vendor_code": "x-medkit-ros2-service-unavailable", "message": "Service call failed", ...}, HTTP status 500 unchanged) instead of the previous bespoke nested{"error": {"code", "message", "details"}}object. This aligns the one remaining non-standard error path with every other gateway error; clients that parsederror.code/error.detailsfor this specific failure must readvendor_code/parametersinstead (#403)GET /api/v1/{entity-path}/datanow publishes the opaqueDataListResultschema ({type: object, additionalProperties: true, x-medkit-opaque: true}), matching howGET .../faultsalready publishesFaultListResult. The wire payload is unchanged for runtime (ROS 2) entities - it is still{"items": [...], "x-medkit": {...}}built from the typedCollection<DataItem, DataListXMedkit>- but for plugin-owned entities the provider’s free-form per-item shape now passes through verbatim instead of being re-parsed intoCollection<DataItem>. This fixes a regression in which plugin per-item fields (the OPC-UA plugin’svalue/unit/data_type/writable) were silently dropped by the typed re-parse. Clients that generated a typedDataItemmodel from the previous spec for this route now see an opaque object instead (#403)Entity responses (areas, components, apps, functions - list items and detail) now always carry a top-level
typediscriminator (an enum ofarea/component/app/function). Previously list items had notypeand detail responses exposed it only insidex-medkit.entityType. Additive and tolerant-client-safe; consumers keying on the entity kind can now read the top-leveltype(#403)ros2_medkit_msgs/srv/ClearFaultrequest gains abool skip_correlation_auto_clearfield (see the per-entity fault scope entry below for the in-tree motivation). Adding a request field changes the service type hash, so out-of-tree callers that invoke the service directly (for exampleros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault ...as documented in theros2_medkit_fault_managerREADME) must rebuild against the newros2_medkit_msgsto keep talking tofault_manager. The in-tree gateway client and server are updated together (#395)Per-entity fault routes are now correctly scoped to the entity’s hosted apps.
GET /api/v1/{entity-path}/faults/{fault_code},DELETE /api/v1/{entity-path}/faults/{fault_code},GET /api/v1/{entity-path}/faults, andDELETE /api/v1/{entity-path}/faultspreviously fell back to a prefix match against the entity’snamespace_path; when that was empty (host-derived / synthetic components, manifest components without anamespacefield, Areas, Functions, and Apps with a wildcardros_binding.namespace_pattern) the scope filter was silently disabled and the routes exposed - and onDELETE, cleared - faults reported by apps that belonged to entirely different entities. All four handlers now resolve the addressed entity to its hosted-app FQN set (via the newHandlerContext::resolve_entity_source_fqnshelper) and apply a strict all-sources scope check: a fault counts as in scope only when every entry in itsreporting_sourcesis owned by the entity (exact FQN match, or strict path-child via<fqn>/...). Per-fault routes return404 Resource Not Foundfor any fault that fails the check; collection routes return an emptyitemsarray. The underlyingGetFault.srvcontract is unchanged;ClearFault.srvgains a newskip_correlation_auto_clearrequest flag so per-entity DELETE can opt out of cascade-clearing correlated symptom fault codes that may live in other entities. Per-entity collection responses no longer include the globalmuted_count/cluster_count/muted_faults/clusterscorrelation metadata; those remain on the globalGET /api/v1/faultsroute. Behavior changes visible to clients: (a) faults reported by apps outside the addressed entity are no longer returned or cleared via that entity’s route, (b) mixed-source faults that include at least one out-of-entity reporter are likewise rejected with404on per-fault routes and excluded from per-entity collection responses (use the globalGET /api/v1/faultsto see them), (c) per-entity DELETE no longer cascade-clears correlated symptoms outside the entity (#395)GET /api/v1/updates/{id}/statusno longer returns404for a registered-but-idle package;POST /api/v1/updatesnow seeds apendingstatus, so the endpoint returns200 {"status": "pending"}immediately after registration.404is reserved for packages that are not registered. Clients that used404as a signal for “registered but nothing started yet” must adapt (#378)
Features:
Typed
fan_out_collection<T>aggregating helper replaces raw-JSONmerge_peer_itemson the typed collection routes (data, operations, config, logs). Peer items are decoded viadto::JsonReader<T>; items that fail validation are removed from the mergeditemsarray, recorded inx-medkit.peer_dropped_itemswith the JsonReader error plus a best-effortsource_id, and logged atWARN. Items that parse successfully are re-serialized through the localdto::JsonWriter<T>, so any peer-supplied fields outside the local DTO schema are dropped from the merged response (the previous raw passthrough preserved unknown peer fields verbatim). Previously, malformed peer items silently disappeared into the merged response; fleet operators can now detect inter-gateway schema drift directly on the wire (#403)Collection<T, XMedkitT>is now a 2-parameter template. Domain list endpoints (faults, config, logs) reference their richer per-domain collection x-medkit struct (FaultListXMedkit,ConfigListXMedkit,LogListXMedkit) directly in the published schema instead of the genericXMedkitCollection, so generated clients see aggregation counts, peer provenance, andpeer_dropped_itemsfrom the schema. The data list builds the same typedCollection<DataItem, DataListXMedkit>internally (so the wire still carries those fields) but publishes the opaqueDataListResultenvelope, because plugin-owned data entities can return vendor per-item fields the typed item schema cannot describe (see the data-list breaking-change entry above) (#403)New
opaque_object("key", &T::field)DTO field descriptor indto/contract.hpp. Binds anlohmann::jsonmember as a typed “any JSON object” field:JsonWriteremits it verbatim,JsonReaderrejects scalars / arrays / null,SchemaWriteremits{type: object, additionalProperties: true, x-medkit-opaque: true}. Used for fields whose runtime shape is decided by an upstream component the gateway cannot introspect (live ROS message payloads, plugin-defined fault envelopes, action results) (#403)GET /api/v1/faults/streamevent payloads now carry an optionalx-medkitSOVD payload-extension object withentity_typeandentity_idfields. When the gateway can resolve the fault’s first reporting source back to a SOVD entity (via the manifest-mode linking index, or a runtime-mode last-segment match against an existing App), consumers can hit/{entity_type}/{entity_id}/bulk-data/rosbags/{fault_code}directly instead of HEAD-probing every entity. Resolution is snapshotted at event arrival, so a discovery refresh between enqueue and stream-out cannot retroactively change the entity reported to consumers. Thex-medkitobject is omitted entirely when no entity can be resolved, so existing SSE consumers ignore the addition (#380)Plugin API version bumped to v7. Adds
PluginContext::notify_entities_changed(EntityChangeScope)lifecycle hook for plugins that mutate the entity surface at runtime; default no-op keeps v6 source code compiling unchanged against v7 headers. Binary compatibility is not provided: the plugin loader uses a strict equality check onplugin_api_version(), so out-of-tree plugins must be recompiled (#376)New
discovery.manifest.fragments_dirparameter: gateway scans the directory for*.yaml/*.ymlfragment files on every manifest load / reload and merges apps, components, and functions on top of the base manifest. Fragments are forbidden from declaring top-levelareas,metadata,discovery,scripts,capabilities, orlock_overrides- those stay in the base manifest. Presence of any forbidden key (including empty-valued ones likeareas: []) is reported as aFRAGMENT_FORBIDDEN_FIELDvalidation error that fails the load / reload. Unknown top-level keys (typos such asapp:vsapps:) are ignored with a warning log. Files merged in alphabetical order for deterministic duplicate-id errors (#376)Fragment files are size-capped at 1 MiB (
ManifestParser::kMaxFragmentBytes) before being read into memory, and any symlink resolving outside the canonicalfragments_diris skipped with a warning, so misconfigurations or symlink-based escapes cannot hand arbitrary bytes to the YAML parser (#376)All-or-nothing fragment semantics: a single malformed or forbidden fragment fails the entire load / reload and keeps the previously-loaded manifest active (#376)
ManifestParser::parse_fragment_fileconvenience entrypoint that injects a syntheticmanifest_versionheader when the fragment omits oneSee
design/plugin_entity_notifications.rstfor the lifecycle, merge-rule, and plugin-side write-contract walkthroughNew
GET /api/v1/apps/{app_id}/belongs-todiscovery endpoint returning the areas and components an app belongs to; thebelongs-toURI is advertised onGET /apps/{app_id}(#196)Pool-backed
TopicDataProviderfor live topic data: a shared subscription pool owned by a single-writer executor node, with LRU and idle eviction and publisher-QoS matching, replacing per-request subscriptions. Pool and executor health are surfaced as thex-medkit-subscription-executorvendor-extension stats onGET /api/v1/health, read atomically so/healthnever blocks under load (#384)GET /api/v1/updates/{id}/statusexposes the update lifecyclephaseunder the responsex-medkitobjectgateway.launch.pyandgateway_https.launch.pyaccept aconfig_filelaunch argument pointing at an external parameter YAML. Parameters present in the file override the matching gateway defaults; parameters the file omits keep their launch defaults instead of being reset (#408)Plugin-facing headers are httplib-free across the
.soboundary: the handler-result vocabulary (Result,NoContent,Forwarded,ValidatorResult,ResponseAttachments) moved to a new leaf headerhttp/handler_result.hppso provider and DTO interfaces no longer transitively include<httplib.h>. Out-of-tree plugins built against the installed gateway (build-farm / Docker topology, where the vendored httplib is not on the include path) compile again; no ABI, wire, or behaviour change. A pre-push gate and CI scan keep the plugin-facing headers httplib-free (#411)Contributors: @bburda, @eclipse0922, @evTessellate, @mfaferek93
0.4.0 (2026-03-20)
Breaking Changes:
GET /version-inforesponse key renamed fromsovd_infotoitemsfor SOVD alignment (#258)GET /root endpoint restructured:endpointsis now a flat string array, addedcapabilitiesobject,api_basefield, andname/versiontop-level fields (#258)Default rosbag storage format changed from
sqlite3tomcap(#258)Plugin API version bumped to v4 - added
ScriptProvider, locking API, and extendedPluginContextwith entity snapshot, fault listing, and sampler registrationGraphProviderPluginextracted to separateros2_medkit_graph_providerpackage
Features:
Discovery & Merge Pipeline:
Layered merge pipeline for hybrid discovery with per-layer, per-field-group merge policies (#258)
Gap-fill configuration: control heuristic entity creation with
allow_heuristic_*options and namespace filtering (#258)Plugin layer:
IntrospectionProvidernow wired into discovery pipeline viaPluginLayer(#258)/healthendpoint includes merge pipeline diagnostics (layers, conflicts, gap-fill stats) (#258)Entity detail responses now include
logs,bulk-data,cyclic-subscriptionsURIs (#258)Entity capabilities fix: areas and functions now report correct resource collections (#258)
discovery.manifest.enabled/discovery.runtime.enabledparameters for hybrid modeNewEntities.functions- plugins can now produce Function entitiesGET /apps/{id}/is-located-onendpoint for reverse host lookup (app to component)Beacon discovery plugin system - push-based entity enrichment via ROS 2 topic
x-medkit-topic-beaconandx-medkit-param-beaconvendor extension REST endpointsLinux introspection plugins: procfs, systemd, and container plugins via
x-medkit-*vendor endpoints (#263)
Locking:
SOVD-compliant resource locking: acquire, release, extend with session tracking and expiration
Lock enforcement on all mutating handlers (PUT, POST, DELETE)
Per-entity lock configuration via manifest YAML with
required_scopesLock API exposed to plugins via
PluginContextAutomatic cyclic subscription cleanup on lock expiry
LOCKScapability in entity descriptions
Scripts:
SOVD script execution endpoints: CRUD for scripts and executions with subprocess execution
ScriptProviderplugin interface for custom script backendsDefaultScriptProviderwith manifest + filesystem CRUD, argument passing, and timeoutManifest-defined scripts:
ManifestParserpopulatesScriptsConfig.entriesfrom manifest YAMLallow_uploadsconfig toggle for hardened deploymentsRBAC integration for script operations
Logging:
LogProviderplugin interface for custom log backends (#258)LogManagerwith/rosoutring buffer and plugin delegation/logsand/logs/configurationendpointsLOGScapability in discovery responsesConfigurable log buffer size via parameters
Area and function log endpoints with namespace aggregation (#258)
Triggers:
Condition-based triggers with CRUD endpoints, SSE event streaming, and hierarchy matching
TriggerManagerwithConditionEvaluatorinterface and 4 built-in evaluators (OnChange, OnChangeTo, EnterRange, LeaveRange)ResourceChangeNotifierfor async dispatch from FaultManager, UpdateManager, and OperationManagerTriggerTopicSubscriberfor data trigger ROS 2 topic subscriptionsPersistent trigger storage via SQLite with restore-on-restart support
TriggerTransportProviderplugin interface for custom trigger delivery
OpenAPI & Documentation:
RouteRegistryas single source of truth for routes and OpenAPI metadataOpenApiSpecBuilderfor full OpenAPI 3.1.0 document assembly withSchemaBuilderandPathBuilderCompile-time Swagger UI embedding (
ENABLE_SWAGGER_UI)Named component schemas with
$ref, cleanoperationIdvalues, endpoint descriptions,GenericErrorschema refs,info.contact, Spectral-clean output, multipart upload schemas, static spec cachingSOVD compliance documentation with resource collection support matrix (#258)
Other:
Multi-collection cyclic subscription support (data, faults, logs, configurations, update-status)
Generation-based caching for capability responses via
CapabilityGeneratorPluginContext::get_child_apps()for Component-level aggregationSub-resource RBAC patterns for all collections
Auto-populate gateway version from
package.xmlvia CMakeNamespaced fault manager integration -
FaultManagerPathsresolves service/topic names for custom namespacesGrouped
fault_manager.*parameter namespace for cleaner configuration
Build:
Extracted shared cmake modules into
ros2_medkit_cmakepackage (#294)Auto-detect ccache for faster incremental rebuilds
Precompiled headers for gateway package
Centralized clang-tidy configuration (opt-in locally, mandatory in CI)
Tests:
Unit tests for DiscoveryHandlers, OperationHandlers, ScriptHandlers, LockHandlers, LockManager, ScriptManager, DefaultScriptProvider
Comprehensive integration tests for locking, scripts, graph provider plugin, beacon plugins, OpenAPI/docs, logging, namespaced fault manager
Contributors: @bburda
0.3.0 (2026-02-27)
Features:
Gateway plugin framework with dynamic C++ plugin loading (#237)
Software updates plugin with 8 SOVD-compliant endpoints (#237, #231)
SSE-based periodic data subscriptions for real-time streaming without polling (#223)
Global
DELETE /api/v1/faultsendpoint (#228)Return HEALED/PREPASSED faults via status filter (#218)
Bulk data upload and delete endpoints (#216)
Token-bucket rate limiting middleware, configurable per-endpoint (#220)
Reduce lock contention in ConfigurationManager (#194)
Cache component topic map to avoid per-request graph rebuild (#212)
Require cpp-httplib >= 0.14 in pkg-config check (#230)
Add missing
ament_index_cppdependency topackage.xml(#191)Unit tests for HealthHandlers, DataHandlers, and AuthHandlers (#232, #234, #233)
Standardize include guards to
#pragma once(#192)Use
foreachloop for CMake coverage flags (#193)Migrate
ament_target_dependenciesto compat shim for Rolling (#242)Multi-distro CI support for ROS 2 Humble, Jazzy, and Rolling (#219, #242)
Contributors: @bburda, @eclipse0922, @mfaferek93
0.2.0 (2026-02-07)
Initial rosdistro release
HTTP REST gateway for ros2_medkit diagnostics system
SOVD-compatible entity discovery with four entity types:
Areas, Components, Apps, Functions
HATEOAS links and capabilities in all responses
Relationship endpoints (subareas, subcomponents, related-apps, hosts)
Three discovery modes:
Runtime-only: automatic ROS 2 graph introspection
Manifest-only: YAML manifest with validation (11 rules)
Hybrid: manifest as source of truth + runtime linking
REST API endpoints:
Fault management: GET/POST/DELETE /api/v1/faults
Data access: topic sampling via GenericSubscription
Operations: service calls and action goals via GenericClient
Configuration: parameter get/set via ROS 2 parameter API
Snapshots: GET /api/v1/faults/{code}/snapshots
Rosbag: GET /api/v1/faults/{code}/snapshots/bag
Server-Sent Events (SSE) at /api/v1/faults/stream:
Multi-client support with thread-safe event queue
Keepalive, Last-Event-ID reconnection, configurable max_clients
JWT-based authentication with configurable policies
HTTPS/TLS support via OpenSSL and cpp-httplib
Native C++ ROS 2 serialization via ros2_medkit_serialization (no CLI dependencies)
Contributors: Bartosz Burda, Michal Faferek
Changelog for package ros2_medkit_fault_manager
0.6.0 (2026-06-22)
Bounded concurrent snapshot capture under fault storms with a
CaptureThreadPooland configurable capture pool / queue / overflow-policy parameters. The rosbag leg is serialized and the cooldown map is bounded, so a burst of simultaneous faults can no longer exhaust capture threads or grow memory without limit (#456)Entity-scoped rosbag capture by default (#431)
Made rosbag capture enablement crash-safe (#430)
Contributors: @bburda, @mfaferek93
0.5.0 (2026-06-08)
ClearFaulthonors the newskip_correlation_auto_clearrequest flag so per-entity fault clears can opt out of cascade-clearing correlated symptom fault codes (#395)Three-layer protection against unbounded snapshot growth (bounded buffers plus pruning)
Concurrency and lifetime hardening: serialize concurrent subscription creation in
SnapshotCapture, join capture threads in theFaultManagerNodedestructor, and defense-in-depth shutdown guards to prevent teardown crashes across distrosAggregation security hardening and improved test coverage
Build: adopt the centralized
ROS2MedkitWarningsandROS2MedkitSanitizerscmake modules andbugprone/special-member-functionsclang-tidy checksContributors: @bburda
0.4.0 (2026-03-20)
Per-entity confirmation and healing thresholds via manifest configuration (#269)
Default rosbag storage format changed from
sqlite3tomcapSupport for namespaced fault manager nodes - gateway resolves service/topic names when the fault manager runs in a custom namespace
Build: use shared cmake modules from
ros2_medkit_cmakepackageBuild: centralized clang-tidy configuration
Contributors: @bburda
0.3.0 (2026-02-27)
0.2.0 (2026-02-07)
Initial rosdistro release
Central fault management node with ROS 2 services:
ReportFault - report FAILED/PASSED events with debounce filtering
GetFaults - query faults with filtering by severity, status, correlation
ClearFault - clear/acknowledge faults
Debounce filtering with configurable thresholds:
FAILED events decrement counter, PASSED events increment
Configurable confirmation_threshold (default: -1, immediate)
Optional healing support (healing_enabled, healing_threshold)
Time-based auto-confirmation (auto_confirm_after_sec)
CRITICAL severity bypasses debounce
Dual storage backends:
SQLite persistent storage with WAL mode (default)
In-memory storage for testing/lightweight deployments
Snapshot capture on fault confirmation:
Topic data captured as JSON with configurable topic resolution
Priority: fault_specific > patterns > default_topics
Stored in SQLite with indexed fault_code lookup
Auto-cleanup on fault clear
Rosbag capture with ring buffer:
Configurable duration, post-fault recording, topic selection
Lazy start mode (start on PREFAILED) or immediate
Auto-cleanup of bag files, storage limits (max_bag_size_mb)
GetRosbag service for bag file metadata
Fault correlation engine:
Hierarchical mode: root cause to symptom relationships
Auto-cluster mode: group similar faults within time window
YAML-based configuration with pattern wildcards
Muted faults tracking, auto-clear on root cause resolution
FaultEvent publishing on ~/events topic for SSE streaming
Wall clock timestamps (compatible with use_sim_time)
Contributors: Bartosz Burda, Michal Faferek
Changelog for package ros2_medkit_fault_reporter
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
LocalFilternow debouncesPASSEDevents with the same threshold / window filtering asFAILED, preventing rapid CONFIRMED/CLEARED status cycling from triggering unbounded snapshot recapture (#308)Build: adopt the centralized
ROS2MedkitWarningsandROS2MedkitSanitizerscmake modulesContributors: @bburda, @mfaferek93
0.4.0 (2026-03-20)
Build: use shared cmake modules from
ros2_medkit_cmakepackageBuild: auto-detect ccache, centralized clang-tidy configuration
Contributors: @bburda
0.3.0 (2026-02-27)
0.2.0 (2026-02-07)
Initial rosdistro release
FaultReporter client library with simple API:
report(fault_code, severity, description) - report FAILED events
report_passed(fault_code) - report fault condition cleared
High-severity faults (ERROR, CRITICAL) bypass local filtering
LocalFilter for per-fault-code threshold/window filtering:
Configurable threshold (default: 3 reports) and time window (default: 10s)
Prevents flooding FaultManager with duplicate reports
PASSED events always forwarded (bypass filtering)
Configuration via ROS parameters (filter_threshold, filter_window_sec)
Thread-safe implementation with mutex-protected config access
Contributors: Bartosz Burda, Michal Faferek
Changelog for package ros2_medkit_diagnostic_bridge
0.6.0 (2026-06-22)
Tests: label
test_integrationas an integration test so it runs in the integration suite instead of the unit set (#443)Contributors: @bburda
0.5.0 (2026-06-08)
Build: adopt the centralized
ROS2MedkitWarningsandROS2MedkitSanitizerscmake modulesTests: use centralized
ROS_DOMAIN_IDallocation for DDS isolationContributors: @bburda
0.4.0 (2026-03-20)
Build: use shared cmake modules from
ros2_medkit_cmakepackageBuild: auto-detect ccache, centralized clang-tidy configuration
Contributors: @bburda
0.3.0 (2026-02-27)
0.2.0 (2026-02-07)
Initial rosdistro release
Bridge node converting standard ROS 2 /diagnostics to FaultManager fault reports
Severity mapping:
OK -> PASSED event (fault condition cleared)
WARN -> WARN severity FAILED event
ERROR -> ERROR severity FAILED event
STALE -> CRITICAL severity FAILED event
Auto-generated fault codes from diagnostic names (UPPER_SNAKE_CASE)
Custom name_to_code mappings via ROS parameters
Stateless design: always sends PASSED for OK status (handles restarts)
Contributors: Michal Faferek
Changelog for package ros2_medkit_log_bridge
0.6.0 (2026-06-22)
Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes (#422)Ships a default configuration so the bridge starts out of the box (#449)
Skips the medkit stack’s own nodes by default, matching on the raw logger name (#460)
Contributors: @mfaferek93
Changelog for package ros2_medkit_action_status_bridge
0.6.0 (2026-06-22)
Initial release: generic action-status bridge. Watches every
/<action>/_action/statustopic and turns ABORTED goals into FaultManager faults (<PREFIX>_<ACTION>_ABORTED), heals on a non-failing terminal state. Captures the terminal action verdict that the diagnostic and log bridges cannot see (#423).Fault state is per-ACTION, derived from the whole
GoalStatusArrayon each message: a fault is raised only on thehealthy -> failedtransition and healed only onfailed -> healthy, so it is order-independent and resilient to dropped terminal messages. Per-goal dedup now only suppresses duplicate log lines.canceled_is_faultemits a status-aware<PREFIX>_<ACTION>_CANCELEDcode; such a fault heals on the next non-failing terminal or when the canceled goal ages out of the retained status array.Vanished actions (lifecycle deactivate, one-shot nodes) are pruned on rescan.
Parameters are range-checked/normalized at load; an incompatible action status QoS is now warned about instead of silently dropping faults.
Ships a default configuration so the bridge starts out of the box (#459)
Fault source is fixed at first report instead of being re-attributed later: faults raised before discovery settles register the server FQN, faults are never attributed to the discovery placeholder node name, and the subscriptions and timer are reset in the destructor (#466)
Contributors: @bburda, @mfaferek93
Changelog for package ros2_medkit_serialization
0.6.0 (2026-06-22)
TypeIntrospectionresolves service and actiontype_infoschemas lazily and caches them as shared, immutable per-type objects, so discovery no longer rebuilds and deep-copies operation schemas on every refresh (#462)Contributors: @bburda
0.5.0 (2026-06-08)
TypeIntrospectionrelocated into this package as part of the gateway core / ROS 2 layer splitBuild: adopt the centralized
ROS2MedkitWarningsandROS2MedkitSanitizerscmake modulesContributors: @bburda
0.4.0 (2026-03-20)
Enable
POSITION_INDEPENDENT_CODEfor MODULE target compatibilityBuild: use shared cmake modules from
ros2_medkit_cmakepackageBuild: auto-detect ccache, centralized clang-tidy configuration
Contributors: @bburda
0.3.0 (2026-02-27)
0.2.0 (2026-02-07)
Initial rosdistro release
Runtime JSON to ROS 2 message serialization using vendored dynmsg C++ API
TypeCache - thread-safe caching of ROS type introspection data with shared_mutex for read concurrency
JsonSerializer - bidirectional JSON <-> ROS message conversion via dynmsg YAML bridge, including CDR serialization/deserialization for GenericClient/GenericSubscription
ServiceActionTypes - helper utilities for resolving service and action internal types (request/response, goal/result/feedback)
SerializationError exception hierarchy for structured error handling
Contributors: Bartosz Burda
Changelog for package ros2_medkit_msgs
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
New service definitions
ListEntities.srv,GetEntityData.srv,GetCapabilities.srvand theEntityInfo.msgtype for exposing the entity tree over ROS 2 services (#330)ClearFault.srvrequest gains abool skip_correlation_auto_clearfield so callers can opt out of cascade-clearing correlated symptom fault codes; out-of-tree callers must rebuild against the new message (#395)Contributors: @bburda, @mfaferek93
0.4.0 (2026-03-20)
MedkitDiscoveryHintmessage type for beacon discovery publishersContributors: @bburda
0.3.0 (2026-02-27)
0.2.0 (2026-02-07)
Initial rosdistro release
Fault management messages:
Fault.msg - Core fault data model with severity levels (INFO/WARN/ERROR/CRITICAL) and debounce-based status lifecycle (PREFAILED/PREPASSED/CONFIRMED/HEALED/CLEARED)
FaultEvent.msg - Real-time event notifications (EVENT_CONFIRMED/EVENT_CLEARED/EVENT_UPDATED) with auto-cleared correlation codes
MutedFaultInfo.msg - Fault correlation muting metadata
ClusterInfo.msg - Fault clustering information
Fault management services:
ReportFault.srv - Report fault events with FAILED/PASSED event model
GetFaults.srv - Query faults with filtering by severity, status, and correlation data
ClearFault.srv - Clear/acknowledge faults by fault_code
GetSnapshots.srv - Retrieve topic snapshots captured at fault time
GetRosbag.srv - Retrieve rosbag recordings associated with faults
Contributors: Bartosz Burda, Michal Faferek
Changelog for package ros2_medkit_integration_tests
0.6.0 (2026-06-22)
0.5.0 (2026-06-08)
New peer-aggregation suites: peer aggregation, cross-ECU fan-out across all resource types, daisy-chain hierarchical aggregation, leaf-collision aggregation, and cross-ECU log aggregation
New SOVD-aligned entity-model suites: runtime entity model, flat entity tree without areas, hybrid suppression, and per-entity fault scope isolation
New OpenAPI conformance suites:
test_openapi_callabilityandtest_openapi_response_driftvalidate the published spec against live responsesNew graph-event discovery suite covering rclcpp graph-event driven discovery refresh
Coverage for the
GET /apps/{id}/belongs-todiscovery endpoint, nestedx-medkitvendor payloads (#385), version-info aggregation, and pending-after-register update status (#378)Tests: centralized
ROS_DOMAIN_IDallocation and widened shutdown timeouts for sanitizer overheadContributors: @bburda, @eclipse0922
0.4.0 (2026-03-20)
Integration tests for SOVD resource locking (acquire, release, extend, fault clear with locks, expiration, parent propagation)
Integration tests for SOVD script execution endpoints (all formats, params, output, failure, lifecycle)
Integration tests for graph provider plugin (external plugin loading, entity introspection)
Integration tests for beacon discovery plugins (topic beacon, parameter beacon)
Integration tests for OpenAPI/docs endpoint
Integration tests for logging endpoints (
/logs,/logs/configuration)Integration tests for linux introspection plugins (launch_testing and Docker-based)
Port isolation per integration test via CMake-assigned unique ports
ROS_DOMAIN_IDisolation for integration testsBuild: use shared cmake modules from
ros2_medkit_cmakepackageContributors: @bburda
0.3.0 (2026-02-27)
Changelog for package ros2_medkit_cmake
0.6.0 (2026-06-22)
ROS2MedkitTestDomain: carve dedicatedROS_DOMAIN_IDranges for the new log bridge (210-214) and action-status bridge (215-219) test suites out of the integration-tests range (#422)Contributors: @mfaferek93
0.5.0 (2026-06-08)
ROS2MedkitWarnings.cmakemodule centralizes compiler warning flags across all packages, with selective-Werror(namespacedMEDKIT_ENABLE_WERROR, defaults OFF) applied only to flags safe against external headersROS2MedkitSanitizers.cmakemodule adds ASan/UBSan and TSan support for sanitizer CI jobsROS2MedkitTestDomain.cmakecentralizesROS_DOMAIN_IDallocation for per-test DDS isolationVendored cpp-httplib 0.14.3 as a build-farm fallback (
VENDORED_DIRparameter), marked as a SYSTEM include to suppress third-party warningsmedkit_find_cpp_httplibcaps cpp-httplib at< 0.20across both the pkg-config andfind_package(httplib)tiers, so distros shipping 0.20+ (Ubuntu 26.04 ships 0.26, which dropped the multipartRequest::has_fileAPI the gateway uses) fall through to the vendored 0.14.3 header instead of failing the build;ROS2MedkitCompat.cmakeextended to cover ROS 2 Lyrical / Ubuntu 26.04 Resolute (rclcpp 32,yaml_cpp_vendortarget export,ament_target_dependenciesremoval in ament_cmake 2.8.5+), which replaces Rolling in CI (#405)Contributors: @bburda, @mfaferek93
0.4.0 (2026-03-20)
Initial release - shared cmake modules extracted from gateway package (#294)
ROS2MedkitCcache.cmake- auto-detect ccache for faster incremental rebuildsROS2MedkitLinting.cmake- centralized clang-tidy configuration (opt-in locally, mandatory in CI)ROS2MedkitCompat.cmake- multi-distro compatibility shims for ROS 2 Humble/Jazzy/RollingContributors: @bburda
Changelog for package ros2_medkit_linux_introspection
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
Migrated the introspection plugins to the
get_routes()plugin APIDeclared
pkg-configas abuildtool_dependand fixed a route-separator bugBuild: adopt the centralized
ROS2MedkitWarningsandROS2MedkitSanitizerscmake modulesContributors: @bburda
0.4.0 (2026-03-20)
Initial release - Linux process introspection plugins for ros2_medkit gateway
procfs_plugin- process-level diagnostics via/procfilesystem (CPU, memory, threads, file descriptors)systemd_plugin- systemd unit status and resource usage via D-Buscontainer_plugin- container runtime detection and cgroup resource limitsPidCachewith TTL-based refresh for efficient PID-to-node mappingproc_readerandcgroup_readerutilities with configurable proc rootCross-distro support for ROS 2 Humble, Jazzy, and Rolling
Contributors: @bburda
Changelog for package ros2_medkit_beacon_common
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
Updated include paths for the gateway core / ROS 2
PluginContextlayer split and removal of backwards-compat shim headersBuild: adopt the centralized
ROS2MedkitWarningscmake moduleContributors: @bburda
0.4.0 (2026-03-20)
Initial release - shared utilities for beacon discovery plugins
BeaconHintStorewith TTL-based hint transitions and thread safetyBeaconValidatorinput validation gateBeaconEntityMapperto convert discovery hints intoIntrospectionResultbuild_beacon_response()shared response builderBeaconPluginbase class for topic and parameter beacon pluginsTokenBucketrate limiter with thread-safe accessContributors: @bburda
Changelog for package ros2_medkit_param_beacon
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
Migrated
ParameterBeaconPluginto theget_routes()plugin APIAdded shutdown guards and
noexceptdestructors that reset rclcpp resources before member destruction, preventing teardown SIGSEGV; the graph poll now swallowsrcl“context invalid” during shutdownAdded post-shutdown guard unit tests
Build: adopt the centralized
ROS2MedkitWarningscmake moduleContributors: @bburda
0.4.0 (2026-03-20)
Initial release - parameter-based beacon discovery plugin
ParameterBeaconPluginwith pull-based parameter reading for entity enrichmentx-medkit-param-beaconvendor extension REST endpointPoll target discovery from ROS graph in non-hybrid mode
ParameterClientInterfacefor testable parameter accessContributors: @bburda
Changelog for package ros2_medkit_topic_beacon
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
Migrated
TopicBeaconPluginto theget_routes()plugin APIAdded shutdown guards and
noexceptdestructors (withoverride) that reset rclcpp resources before member destruction, preventing teardown SIGSEGVAdded post-shutdown guard unit tests
Build: adopt the centralized
ROS2MedkitWarningscmake moduleContributors: @bburda
0.4.0 (2026-03-20)
Initial release - topic-based beacon discovery plugin
TopicBeaconPluginwith push-based topic subscription for entity enrichmentx-medkit-topic-beaconvendor extension REST endpointStamp-based TTL for topic beacon hints
Diagnostic logging for beacon hint processing
Contributors: @bburda
Changelog for package ros2_medkit_graph_provider
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
Migrated
GraphProviderPluginto theget_routes()plugin API and fixed a route-separator bugAdded shutdown guards and
noexceptdestructors that reset rclcpp resources before member destruction, preventing teardown SIGSEGVAdded post-shutdown guard unit tests; dropped the cpp-httplib source install from the Dockerfile (now vendored via
ros2_medkit_cmake)Build: adopt the centralized
ROS2MedkitWarningscmake moduleContributors: @bburda
0.4.0 (2026-03-20)
Initial release - extracted from
ros2_medkit_gatewaypackageGraphProviderPluginfor ROS 2 graph-based entity introspectionStandalone external plugin package with independent build and test
Locking support via
PluginContextAPIContributors: @bburda
Changelog for package ros2_medkit_opcua
0.6.0 (2026-06-22)
No functional changes; version bump for the coordinated 0.6.0 release.
Contributors: @bburda
0.5.0 (2026-06-08)
Native OPC-UA Part 9
AlarmConditionTypeevent subscription. The plugin now subscribes to vendor-defined alarms (Siemens S7-1500Program_Alarm/ ProDiag, Beckhoff TF6100, CodeSys 3.5+, Rockwell via FactoryTalk Linx) and bridges each event into the SOVD fault lifecycle. Configured via a new top-levelevent_alarms:block in the node map YAML; mutually exclusive per entry with the existing threshold-basedalarmform. (issue #386)New SOVD operations on entities that host alarm sources:
acknowledge_faultinvokes the inheritedAcknowledgemethod on the liveConditionId(i=9111, EventId tracked per Part 9 §5.7.3);confirm_faultinvokesConfirm(i=9113). Both accept an optionalcommentrendered asLocalizedTexton the server.OpcuaClientgainsadd_event_monitored_item/remove_event_monitored_item/call_methodand a generation counter that filters callbacks fired from defunct subscriptions after a reconnect. Heap-ownedEventCallbackContextresolves the open62541pp / raw-C lifetime hazard.Header-only
AlarmStateMachinemappingEnabledState x ShelvingState x ActiveState x AckedState x ConfirmedState x BranchIdto SOVDCONFIRMED / HEALED / CLEARED / Suppressed. Full transition table documented indesign/index.rst.ConditionRefresh(Server method i=3875) is invoked on subscribe and on every reconnect, withRefreshStartEvent/RefreshEndEventbracketing tracked for diagnostics.New
test_alarm_serverfixture (open62541-based, full namespace 0 + alarms enabled) emits AlarmConditionType events on stdin commands; integration testrun_alarm_tests.shruns in CI alongside the existing OpenPLC threshold suite. The fixture builds by default via the workspacecolcon build(gated onMEDKIT_OPCUA_BUILD_ALARM_SERVERwhich defaults to ON;ExternalProject_Addrebuilds open62541 withUA_NAMESPACE_ZERO=FULLand alarms ON, with a serial sub-build to dodge the upstream-jrace onnamespace0_generated.c).New CTest wrapper
test_alarm_server_smokeboots the fixture on an ephemeral port and runs the asyncua smoke test against it; skips with CTest exit 77 (treated as pass) whenasyncuais not importable, so iterating on plugin code without the Python dependency does not fail the suite.Contributors: @mfaferek93, @bburda
0.4.0 (2026-04-11)
Initial release
OpcuaPluginimplementation ofGatewayPluginandIntrospectionProviderthat bridges OPC-UA capable PLCs into the SOVD entity treeREST endpoints via the new
get_routes()plugin API:x-plc-data,x-plc-operations,x-plc-statusVendor capabilities registered per entity - only PLC-backed apps and the PLC runtime component advertise the
x-plc-*endpointsFull OPC 10000-6 section 5.3.1.10 node identifier support (
i=numeric,s=string,g=GUID,b=opaque ByteString); example node maps for OpenPLC, Siemens S7-1500 TIA Portal, Beckhoff TwinCAT 3, Allen-Bradley via Kepware and KUKA KR C5NodeMapdriven by YAML configuration - same binary serves any OPC-UA compliant server by changing the node map fileDeterministic entity ordering in
IntrospectionResultoutput (entries sorted by id)Threshold-based PLC alarm detection routed to SOVD faults via
ros2_medkit_msgsservicesReportFault/ClearFaultOptional bridging of numeric PLC values to ROS 2
std_msgs/Float32topics fromset_context()Type-aware writes with per-node range validation
Robust connection-loss detection: all three OPC-UA client paths (
read_value,read_values,write_value) mark the connection as dropped on terminal status codes soOpcuaPollerreconnect kicks in without stallingPolling mode (default) and OPC-UA subscription mode, backed by
open62541ppv0.16.0Integration test suite against an OpenPLC IEC 61131-3 tank demo container
Contributors: @mfaferek93
Changelog for package ros2_medkit_sovd_service_interface
0.6.0 (2026-06-22)
list_entity_faultshandles a faultstatusreturned as an object (not just a string), supporting peer-fault aggregation across daisy-chained gateways (#419)Contributors: @bburda
0.5.0 (2026-06-08)
Initial release - gateway plugin that exposes the medkit entity tree and fault data over standard ROS 2 services, so other ROS 2 nodes can query entities and faults without going through the HTTP API (#330)
Creates ROS 2 services under a configurable prefix (default
/medkit):list_entities,list_entity_faults, andget_capabilities; aget_entity_dataservice is also registered but currently returns “not implemented” (use the HTTP REST API for topic data) pending (#351)Runs as a gateway MODULE plugin with read-only
PluginContextaccess to the entity cache and fault manager; implements no provider interfacesShutdown guards and
noexceptdestructors reset ROS resources before member destruction to prevent teardown crashesContributors: @bburda, @mfaferek93