Highlights
Resource locking
Acquire, release, and extend locks with session tracking and automatic expiration. Lock enforcement is applied to all mutating handlers (PUT, POST, DELETE), with per-entity lock scopes configurable via manifest YAML. Plugins can access lock state via PluginContext. Cyclic subscriptions are automatically cleaned up on lock expiry. (#287)
Diagnostic scripts
Upload, list, execute, and control diagnostic scripts via REST. The ScriptProvider plugin interface lets you bring your own execution backend. The built-in DefaultScriptProvider supports manifest-defined and filesystem-uploaded scripts with argument passing, timeout enforcement, and concurrent execution limits. RBAC guards all operations. (#286, #304)
Condition-based triggers
Event-driven push notifications for resource changes. Define triggers with conditions (OnChange, OnChangeTo, EnterRange, LeaveRange) on any resource collection - data, faults, logs, configurations, or update-status. Triggers fire via SSE and persist across gateway restarts via SQLite. Plugin authors can add custom delivery transports via TriggerTransportProvider. (#293)
Multi-collection cyclic subscriptions
Cyclic subscriptions now support all resource collections - data, faults, logs, configurations, and update-status. Previously limited to data topics, you can now stream any resource type via SSE with configurable intervals. Function-level cyclic subscriptions aggregate from child apps. (#254, #270)
OpenAPI 3.1.0 spec and Swagger UI
The gateway now serves a full OpenAPI 3.1.0 specification at /api/v1/docs with per-entity-type sub-specs, named component schemas, clean operationId values, and endpoint descriptions suitable for client code generation. Swagger UI can be embedded at build time with -DENABLE_SWAGGER_UI=ON. (#271, #302)
Log endpoints
LogManager with /rosout ring buffer and plugin delegation via LogProvider. New /logs and /logs/configuration endpoints with area and function-level namespace aggregation. (#245)
Layered merge pipeline
Hybrid discovery now uses a multi-layer merge pipeline with per-layer, per-field-group merge policies. Manifest, runtime, and plugin layers each contribute entities that are merged according to configurable rules. Gap-fill heuristics are controllable via allow_heuristic_* options. (#246, #258)
Plugins
GraphProviderPlugin (ros2_medkit_graph_provider) builds pipeline graph documents for functions with topic-level metrics - frequency (Hz), latency (ms), drop rate - and pipeline health analysis (healthy/degraded/error edges, bottleneck detection). Exposed via x-medkit-graph vendor extension endpoints on functions. (#270, #289)
Beacon discovery plugins enrich entities with runtime metadata that the ROS 2 graph API cannot provide - transport type, process IDs, hostnames, function membership, and more. TopicBeaconPlugin (push-based): nodes publish MedkitDiscoveryHint messages. ParameterBeaconPlugin (pull-based): the plugin polls node parameters. Both feed into the merge pipeline's plugin layer. (#264)
Linux introspection plugins - procfs, systemd, and container - expose process-level diagnostics (CPU, memory, file descriptors, cgroup limits) via x-medkit-* vendor extension endpoints. (#263)
Plugin API bumped to v4 with ScriptProvider, locking API, and extended PluginContext (entity snapshot, fault listing, sampler registration, child app access).
What's Changed
Features
- feat(logging): add Log Entries REST API endpoints by @bburda in #245
- Add layered MergePipeline for multi-source entity discovery by @bburda in #246
- Support all SOVD resource collections in cyclic subscriptions by @bburda in #254
- feat: Linux introspection plugins (procfs, systemd, container) by @bburda in #263
- feat(discovery): add beacon-based discovery plugins (topic + parameter) by @bburda in #264
- feat: add /docs endpoint with OpenAPI capability description by @bburda in #271
- feat(locking): implement SOVD resource locking by @bburda in #287
- feat: SOVD diagnostic scripts with plugin-extensible ScriptProvider by @bburda in #286
- feat(triggers): implement event-based conditional data delivery by @bburda in #293
- feat(openapi): add response schemas, component types, and operationIds for client code generation by @bburda in #302
- feat(manifest): support scripts section in entity manifest by @bburda in #304
- Add x-medkit-graph provider and function cyclic subscriptions by @eclipse0922 in #270
- Add GET /apps/{app-id}/is-located-on endpoint by @eclipse0922 in #299
- feat: per-entity confirmation and healing thresholds by @mfaferek93 in #274
Bug Fixes & Improvements
- docs+fix: update documentation and API responses for post-0.3.0 changes by @bburda in #258
- Fix exceptions getting bulk_data.categories and plugins at startup by @nnarain in #256
- fix(rosbag): default storage format sqlite3 -> mcap by @mfaferek93 in #252
- fix(deps): use correct rosdep key for SQLite3 by @mfaferek93 in #250
- fix(gateway): support namespaced fault manager integration by @eclipse0922 in #301
- fix: align discovery plugin package versions to 0.3.0 by @mfaferek93 in #292
Testing
- Add unit tests for DiscoveryHandlers by @eclipse0922 in #281
- Add unit tests for operation handlers by @eclipse0922 in #290
CI & Build
- Optimize local DX and CI pipeline by @bburda in #239
- ci: trigger selfpatch_demos CI on push to main by @bburda in #244
- fix(ci): match Jenkins build farm dependency isolation by @bburda in #280
- fix(ci): resolve graph provider test deadlock and clang-tidy timeout by @bburda in #283
- fix(test): resolve buildfarm executor shutdown deadlock in graph provider tests by @bburda in #285
- feat: extract shared cmake modules into ros2_medkit_cmake package by @bburda in #295
- Extract GraphProviderPlugin to loadable .so plugin by @bburda in #289
- feat: experimental cross-platform Pixi support by @bburda in #266
Docs
- docs: rewrite copilot-instructions.md for effective code review by @bburda in #247
- Release v0.4.0 by @bburda in #298
New Contributors
Full Changelog: 0.3.0...0.4.0