Repository navigation
chore(deps): Bump the bowire group with 6 updates - #33
Closed
dependabot[bot] wants to merge 1 commit into
Closed
dependabot[bot] wants to merge 1 commit into
dependabot[bot] wants to merge 1 commit into
Conversation
Bumps Kuestenlogik.Bowire.Protocol.Amqp from 0.2.1 to 1.0.1 Bumps Kuestenlogik.Bowire.Protocol.Grpc from 1.6.0 to 2.1.1 Bumps Kuestenlogik.Bowire.Protocol.Rest from 1.6.0 to 2.1.1 Bumps Kuestenlogik.Bowire.Protocol.SignalR from 1.6.0 to 2.1.1 Bumps Kuestenlogik.Bowire.Protocol.Sse from 1.6.0 to 2.1.1 Bumps Kuestenlogik.Bowire.Protocol.WebSocket from 1.6.0 to 2.1.1 --- updated-dependencies: - dependency-name: Kuestenlogik.Bowire.Protocol.Amqp dependency-version: 1.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.Grpc dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.Grpc dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.Rest dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.Rest dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.SignalR dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.SignalR dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.Sse dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.Sse dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.WebSocket dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire - dependency-name: Kuestenlogik.Bowire.Protocol.WebSocket dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: bowire ... Signed-off-by: dependabot[bot] <support@github.com>
Contributor
Author
LabelsThe following labels could not be found: Please fix the above issues or remove invalid values from |
Contributor
Author
|
Dependabot could not find a dependency.. Because of this, Dependabot cannot update this pull request. |
1 similar comment
Contributor
Author
|
Dependabot could not find a dependency.. Because of this, Dependabot cannot update this pull request. |
Contributor
Author
|
Looks like these dependencies are updatable in another way, so this is no longer needed. |
dependabot
Bot
deleted the
dependabot/nuget/harbor-demo/src/Kuestenlogik.Bowire.Samples.Amqp/bowire-b316666265
branch
July 12, 2026 12:16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Updated Kuestenlogik.Bowire.Protocol.Amqp from 0.2.1 to 1.0.1.
Release notes
Sourced from Kuestenlogik.Bowire.Protocol.Amqp's releases.
1.0.1
What's Changed
New Contributors
Full Changelog: Kuestenlogik/Bowire.Protocol.Amqp@v1.0.0...v1.0.1
1.0.0
Full Changelog: Kuestenlogik/Bowire.Protocol.Amqp@v0.2.2...v1.0.0
1.0.0-rc.3
Full Changelog: Kuestenlogik/Bowire.Protocol.Amqp@v1.0.0-rc.2...v1.0.0-rc.3
1.0.0-rc.2
Full Changelog: Kuestenlogik/Bowire.Protocol.Amqp@v1.0.0-rc.1...v1.0.0-rc.2
1.0.0-rc.1
Full Changelog: Kuestenlogik/Bowire.Protocol.Amqp@v0.2.2...v1.0.0-rc.1
0.2.2
What's Changed
New Contributors
Full Changelog: Kuestenlogik/Bowire.Protocol.Amqp@v0.2.0...v0.2.2
Commits viewable in compare view.
Updated Kuestenlogik.Bowire.Protocol.Grpc from 1.6.0 to 2.1.1.
Release notes
Sourced from Kuestenlogik.Bowire.Protocol.Grpc's releases.
2.1.1
<One-sentence frame for what 2.1 is about. Replaces this placeholder
the moment the first 2.1 work lands.>
Highlights
Bowire as a transparent in-process interceptor —
app.UseBowireInterceptor()(#153)The new interceptor middleware extends Bowire from "the operator drove a call" to "every request flowing through the host."
app.UseBowireInterceptor()registers a pass-through middleware that records method / path / headers / request body / response status / response headers / response body / latency for every request the host receives — from any client, with zero client-side setup, no cert trust, no separate process. Captured flows land in the workbench's new Intercepted rail (sister to the standalone Proxy rail) live over SSE. When the operator starts a recording in the workbench, intercepted flows auto-append as recording steps — point any client at the host, click stop, replay. Standalone reverse-proxy mode (Phase C) and mock injection (Phase D) ship in later releases.MCP-over-MCP forwarder —
bowire mcp serve --attach(#286)A thin Bowire process can now relay every incoming MCP tool call to a heavier Bowire running on the operator's workstation.
bowire mcp serve --attach localhost:5198 --port 5199boots a forwarder that surfaces no local tools —tools/list,tools/call, prompts, resources, and resource templates are all marshalled to the parent and the parent's response is relayed verbatim. Useful when an LLM agent on a CI runner / container should drive the workstation Bowire without sharing the parent's MCP socket directly. The parent gains a matching--token <secret>bearer-auth gate (--bind httponly); the child passes the secret with--attach-token <secret>.Workspace-delete Undo decoupled from Trash (W2a)
The action-log entry for
workspace-deleteis now self-contained: it carries the full snapshot (workspace,data,originalIdx) inline so Undo reads from the entry itself instead of looking the entry up inworkspacesTrashat undo-time. This gives the two surfaces independent retention models:bowire_trash_retention_days(W2).Hard-delete (W2 mode) now writes ONLY the action-log snapshot — there's no trash entry to consult. Soft-delete writes both. Entries persisted BEFORE this change still resolve via the legacy Trash-lookup path (a one-shot
console.infoflags the fallback so the migration window is visible).The other entity-delete resolvers (
recording-delete,flow-delete,env-delete) were audited and already carry their entity payload inline — onlyworkspace-deletehad the Trash coupling.Settings tree organized by scope; Configure + Plugins merged (#325)
The Settings dialog now exposes scope through the parent-node names:
This machine(localStorage / install-scoped) andWorkspace…(.bww-scoped, travels with the workspace file). The per-page disclaimer that used to repeat the scope copy on every sub-page ("These settings stay on this machine — they don't travel with the workspace file (.bww).") is gone — the tree's grouping carries that information unambiguously. The standalonePluginslifecycle leaf is gone; it has merged withConfigureinto a singlePluginsnode whose six sub-pages (Protocols / UI Widgets / Modules / Formats / Tools / Discovery providers) now render the inline per-plugin settings AND the lifecycle button cluster (Restart / Unload / Reset storage, wired to the existingPOST /api/plugins/{id}/lifecycle/{action}501-stub) per row, plus Install + Check-for-updates at the top of the Protocols sub-page. A new empty-stateWorkspace… → Per-Workspace overridespage surfaces every machine-scoped setting that the active workspace has overridden (today: the AI provider config, when the workspace has its ownai-config.<workspaceId>.json); saved deep-links from v2.1 (configure-protocols,plugin-<id>,extension-<id>) keep working unchanged, and any saved value pointing at the droppedpluginslifecycle id migrates toconfigure-protocols.Breaking changes
Mocks + Traffic rails merged into a single Intercept rail
The Mocks rail and the Traffic rail (which itself unified the earlier Proxy + Intercepted rails) have collapsed into one Intercept rail with four sub-tabs in a locked order:
UseBowireInterceptor()(was Traffic → "Flows").The merge eliminates the previous Phase-3 rail bloat where Mocks + Traffic + the already-hidden Intercepted + Proxy descriptors competed for the same conceptual surface ("what do I do with live traffic"). It also disambiguates "Flows" — the orchestration rail keeps the name; what Traffic used to call "Flows" is now "Captured".
Migration is automatic at first paint (idempotent). On boot,
prologue.js:... (truncated)
2.1.0
v2.1 turns Bowire from a discovery + invoke workbench into a real composition surface. The new Compose rail carries a Hoppscotch-style request builder with a protocol picker, per-protocol layouts, history persistence, binary uploads, and full Collections + Presets integration. Underneath, the workbench is now pluggable: rails and modules ship as package contributions, so the standalone Tool, embedded
MapBowire(), and operator-built distributions can pick exactly the surface they want. The new interceptor middleware lets a host hand Bowire every inbound request without client setup. A MapLibre extension + a stand-alone TacticalApi sample demo coordinate-bearing payloads on a live map with bi-directional JSON↔map sync. Streaming subscriptions are now legible, the JSON viewer reaches Hoppscotch parity, and the guided tour walks first-time operators through every rail.300+ commits since v2.0.1. Three packaging breaking changes for embedded hosts: the standalone
Kuestenlogik.Bowire.Rail.Collectionspackage is retired, the wholeRail.package prefix dropped (e.g.Rail.Compose→Compose,Rail.Benchmarks→Benchmarking), and the interceptor surface (Proxy + Intercepted + Traffic rails + the middleware that lived in Core) consolidated into a singleKuestenlogik.Bowire.Interceptorpackage. See Breaking changes below for the one-to-one mapping table. Existing workspaces, collections, recordings, benchmarks load identically; operator-savedrailMode/ enabled-rails state migrates on first boot.Highlights
Compose rail (#293, #289, #290, #291, #295)
The old Design rail is rebranded and rebuilt as Compose — a single-line Hoppscotch-style request bar at the top, per-protocol layout below, history + collections + presets on the side. The protocol picker switches the layout in place: REST gets a URL + KV-table chrome, gRPC gets service / method / JSON body, MCP gets tool / arguments, MQTT gets topic / QoS, WebSocket / SSE get connect / subscribe shells. History persists across reloads, binary uploads ride a base64 side-channel through the wire, and benchmarks can re-run any historical request directly. A Compose tab supports right-click → Duplicate tab so you can fan out a request without losing the original. The toolbar lives where you'd expect (no toolbar in Raw mode, of course).
Pluggable workbench — rails + modules as package contributions (#294)
Bundle.Workbench is now a meta-package: every rail, every module, every extension is a separate project that registers itself via
[BowirePlugin]/[BowireExtension]attributes. The standalone Tool depends on Bundle.Workbench; embedded hosts can drop the bundle and pick per-package references for a smaller surface (e.g. just REST + Compose without the AI module). Bundle.Minimal carries the Core + Home + Discover only — useful for "tiny embedded probe" deployments. Settings → Plugins now lists every loaded protocol AND every UI extension with kind / capability chips so the operator can see what's installed at a glance.Transparent in-process interceptor (#153)
app.UseBowireInterceptor()registers a pass-through middleware that records method / path / headers / request body / response status / response headers / response body / latency for every request the host receives — from any client, with zero client-side setup, no cert trust, no separate process. Captured flows land in the workbench's new Intercepted rail live over SSE. When the operator starts a recording, intercepted flows auto-append as recording steps — point any client at the host, click stop, replay.MapLibre extension + TacticalApi integration (#new)
A new
Kuestenlogik.Bowire.Mapextension auto-mounts a MapLibre GL JS viewer whenever a response carries thecoordinate.wgs84semantic kind. The Wgs84CoordinateDetector picks up{lat, lon},{latitude, longitude}, AND{latitudeCoordinate, longitudeCoordinate}shapes (TacticalAPI naming) anchored by anchored case-insensitive regex. Bidirectional sync: hover on a JSON{lat,lon}block highlights the matching map pin; hover on a pin highlights the JSON. Click on a pin scrolls the JSON to the line and auto-expands collapsed ancestors. Right-click on a coordinate offers Center on map; double-click on either side copies the path to clipboard. A right-side gutter hint surfaces the semantic kind on hover (wgs84 coordinate).The new Sample.TacticalApi server (separate
samples/project) hosts Rheinmetall'sSituationgRPC service with eight NATO-phonetic-callsign tactical entities (Alpha-1 Recon UAV, Bravo-2 Air Defence Btry, …) drifting on a per-object sine-wave so subscriptions feel live. Bundle.Workbench ships theKuestenlogik.Bowire.Protocol.TacticalApiplugin out of the box.Streaming subscriptions, finally legible (#new)
The action button adapts to the active method type: Execute for unary, Subscribe for server-streaming (changes to Stop while a stream is live), Connect / Disconnect for bidirectional and client-streaming. A live state badge in the response pane shows
● Subscribed — 0 msgs→● Receiving — 42 msgs→○ Idle — 42 msgsafter 5 s without a frame →○ Closedon stop →× Erroron stream failure. A statusbar pill lists every active subscription across methods; click → dropdown with switch / stop / copy-path / "stop all". The action button keeps a stable footprint so layout doesn't jitter when methods change.Hoppscotch-parity JSON response viewer + toolbar (#302, #new)
The response viewer renders one JSON line per row with a sticky left gutter carrying line numbers AND the collapse chevron — chevrons line up on the same vertical column regardless of indent depth. Click anywhere on an opener line OR the gutter chevron to toggle. Click = toggle, double-click = Copy path, right-click = unified menu with
Copy ${response.X},Copy path, plus extension-contributed items (Center on mapwhen the map plugin resolves the target). A dedicated JSON toolbar — Expand all, Collapse all, Wrap long lines, Search (Ctrl/Cmd+F), Copy response, Download — sits above the viewer and only renders when the JSON tab is active in tab mode (so the map widget gets its own toolbar real estate). Expand / Collapse rebuild the viewer in place — no full render, so the map's WebGL canvas survives.Tab ↔ Split layout for response viewers (#new)
Server-streaming and unary response panes get a tab-strip with JSON + per-extension widget tab + a layout toggle. Click the toggle → split-pane with JSON on one side, widget on the other; click again → tabs. Per-method layout persists in localStorage so the operator's preference for each method is remembered. The split-layout decision is extension-driven — Core asks the framework
preferredSplitExtensionForMethod(svc, method)rather than hard-coding thecoordinate.wgs84kind. Layering stays clean: Map-specific code inKuestenlogik.Bowire.Map, Core stays generic.Guided tour — page-navigation, alternative paths, per-rail empties (#281, #303)
A spotlight-overlay tour engine walks first-time operators through every rail: workspace creation, source-URL add, method invoke, recording, collection composition, flow building, traffic capture, security scan. Each rail's empty state surfaces its own secondary tour. The tour engine handles dialog-modal yields, alternative paths (e.g. operator already has a workspace), advance modes (
on-cta/on-event/next-button), saved-once dismissal, and reusable fragment includes (_createWorkspaceSteps). Six rail-specific tours land:bowireStartCaptureRecordingTour,bowireStartBuildCollectionTour,bowireStartBuildFlowTour,bowireStartComposeRequestTour,bowireStartCaptureTrafficTour,bowireStartSecurityScanTour.REST auto-probing of well-known OpenAPI paths
When the operator types a bare URL like
http://localhost:5181, the REST plugin now probes a short list of well-known OpenAPI document paths:/openapi.json,/openapi/v1.json,/swagger/v1/swagger.json,/swagger.json,/v3/api-docs,/v3/api-docs.yaml,/api-docs,/openapi.yaml. First valid OpenAPI document wins; the resolved spec URL is cached per origin for the next call. Services are tagged with the operator-supplied URL (not the probed spec URL) so the Discover sidebar groups everything under the URL the operator typed. Skips probing when the supplied URL already looks like a spec URL.Discovery self-origin gate for SSE / WebSocket / SignalR
Three protocol plugins (SSE, WebSocket, SignalR) used to scan the workbench host's own
EndpointDataSourceand return locally-registered endpoints regardless of the source URL the operator asked about. With the Tool's--enable-mcp-adapterflag, the workbench's own/mcproute leaked into every externalserverUrlthe operator added — read as a phantom "SSE Endpoints" service tagged to the wrong source. The newSelfOriginCheck.IsSelfOrigin(serverUrl, sp)helper compares againstIServer.Features.IServerAddressesFeature(with loopback aliases + Kestrel wildcards). Each protocol's discovery now gates its local scan on this check — operator-registered endpoints keep working in both directions.Catalogue plugin — provider seam (#136)
... (truncated)
2.0.1
v2.0.1 is a patch release driven by operator feedback during real workbench use against discovery-enabled targets. The headline work is the complete rewrite of the Freeform Request Builder so it shares chrome with the discovered-method pane, the new self-contained-vs-source URL semantic for collection items, the foundation plumbing for optional rail modules (no default-flip on upgrade), and a stack of critical fixes around error reporting and pane re-rendering. No breaking changes — existing workspaces, collections, recordings, and benchmarks load identically; only the freeform builder + the console error format change visibly.
Highlights
Freeform Request Builder rebuilt on the discovered-method skeleton (#40, #245, #246, #252)
The Freeform Request Builder is now end-to-end consistent with a discovered-method pane: same
.bowire-headerchrome at the top, same.bowire-content[data-split]request/response panes with the draggable divider, same.bowire-action-barat the bottom with Execute. Service + method become editable inputs inside the standard header info column; protocol is a compact icon-popover in the header's right cluster, and the method type lives as a segmented button bar right next to it. URL was lifted out of the Payload/Metadata/Mock tab strip into an identity-level row because the URL determines which tabs make sense — it isn't a payload part. The previous chrome layered freeform-specific overrides on top of the shared classes; those are retired so the padding, font weights, spacing all match exactly.The Execute-button dropdown gains an As new request entry on every discovered method. Clicking it snapshots the current request shape — URL, method, body, metadata, auth, methodType — into the freeform builder pre-filled, with a
cloned: <svc>/<method>lineage hint riding on the Cancel tooltip and the default save name. The discovered service tree stays untouched; the operator edits the clone in place, executes one-shot, or persists it via the header's+ Add to…collection picker. Switching to another method tab and back preserves the clone —freeformRequestis now per-tab session state rather than a singleton that died on the first tab switch.Self-contained vs source-bound URLs in collection items (#252)
Collection items learn a
urlModediscriminator: inline (URL lives verbatim on the item, no central reference) or source (URL is bound to one of the workspace's centrally-managed Source URLs). The freeform builder URL row grows a two-state segmented toggle to pick mode at save time; switching from Inline to Source with a typed-but-unsaved URL prompts to either persist as a new Source then switch, or discard. On replay, items saved withurlMode='source're-resolve their URL against the current Source list — a rename / retirement propagates to every bound item without manual touch-up. Items saved before this release default tourlMode='inline', which preserves their old behaviour exactly.Two compose entry-points land alongside the toggle: Compose new request on the Home rail Quick Actions tile (self-contained URL, the most common case) and New from source… which opens a Source-URL picker before dropping into the builder. Both also surface in the command palette under the new
Newgroup, matching againstcompose,new,request,freeform,ad-hoc. The previous+ Newbutton retired from the Discover toolbar — Discover's job is browsing the discovered tree, not composing, so the action moved to where ad-hoc work actually starts.Rich error detail in the console (#243)
Failed REST / gRPC invocations used to surface as a bare
Errorchip with no body — the actual signal (status code, response body, exception, stack frame) lived on the BowireInvokeResult object but was dropped byproblemTitle. The console-entry path now usesrichErrorDetail, which assembles a multi-line block carrying the title, problem+json status code and reason, detail line, response body (truncated to 4 KB), exception type + message, and the first three non-framework stack frames. Server-side problem+json fields (type,instance, numericstatus) are now picked up correctly — earlier regressions where the helper only looked forstatusCode/httpStatusaliases are fixed so theStatus: 502line lands as expected. Network errors (no response received) still carry the exception text directly.Optional rail modules — plumbing (#248 Phase 1)
Settings → Rail modes editor adds a new section under My preferences where the operator can hide non-essential rails (Recordings, Mocks, Flows, Proxy, Benchmarks, Security) without losing access — disabled rails stay reachable via the command palette and deep links, only the rail icon disappears. Always-on rails (Home, Discover, Workspaces) are hard-coded and can't be toggled. Existing workspaces ship with every rail enabled on upgrade, so no operator sees a surprise hide; the opt-out is explicit. Per-user storage lives in
bowire_enabled_rails; per-workspace overrides land later.This is Phase 1 — pure plumbing, no default-flip. v2.1 (Test pillar) + v2.3 (Security pillar) can ship their new rails as opt-in from day one instead of forcing the always-on assumption, and v2.4's Schema Designer (#247) lands as the first default-OFF module on top of the mechanic this release ships.
User-defined workspace templates (#242)
The Workspaces rail's create-workspace dialog grows a Your templates section between the built-in templates and the last-picked default. The active workspace's "Save as template…" tool button snapshots the current URLs, env vars, collection, global vars, and plugin pins into a localStorage-backed
bowire_user_workspace_templatesrecord. Templates show as click-to-pick entries with a hover-revealed delete (no accidental purges). Rename and delete affordances live next to each row; the user-templateapply(wsId)adapter writes into the new workspace's wsKey buckets exactly the way built-in templates do, so the create-workspace flow is single-pass for both kinds.The default URLs for the built-in templates also change: REST moves from
httpbin.org(no OpenAPI = 0 services) topetstore.swagger.io/v2(discovers a full Pet/Store/User tree on first connect), gRPC moves fromgrpc.postman-echo.com:443(HTTP 502) togrpcs@grpcb.in:443(server-reflection enabled), and Mock + Multi-protocol templates pick up the same discovery-enabled endpoints.Bug fixes
render()before the rail paints (9a91940).loadEnvironmentsFromDiskran even for browser-only workspaces and clobbered the localStorage seed on first paint. Skip path added for non-disk-mode workspaces (e501ad8).setUrlMetaTDZ-style boot race:urlMetawas referenced from a render handler before its assignment; the getter/setter pair now type-guards the variable so a boot-timeensureAliasForUrldoesn't throw (30a0974).OpenApiUploadStore.Clear()so sibling tests can't leak fixtures (30a0974).typeof(MapLibreExtension).Assembly.FullName+ per-test belt-and-suspenders helper (30a0974).CoverageTo95Tests.MapBowireTestAppFactoryContentRoot race: pinned toAppContext.BaseDirectoryso CI'sEnvironment.CurrentDirectorytoggling can't flip the test app's content root mid-run (30a0974).+retire-day crash: the protocol-filter button'sinsertBefore(_, newBtnWrapper)failed after #244 retirednewBtnWrapper; switched toappendChild(b8e1ac3).As new requestno longer flips[+]-tab behaviour:selectedMethod/selectedServiceare preserved when entering the freeform builder so the[+]-tab keeps its "pin current method" behaviour after a clone (62485f9).Polish
selectionClear(dashed rectangle + X) for Clear selection,trashfor Clear all,closefor Close console (1eb4022,b656a36).8b9c116).Coverage
... (truncated)
2.0.0
v2.0 is the cut where every optional surface gets pulled out of the core, the workbench shell gets re-architected end-to-end, and a couple of API-level decisions get unwound now that they have stable replacements. Embedded hosts that vendored
Kuestenlogik.Bowiredirectly will need a small set of explicit changes — see Breaking changes at the bottom.Highlights
Workbench shell re-architected (#115)
The workbench surface that ships in
bowireand embedded hosts was redrawn from the structural level up — Topbar carries identity + workspace context, the left rail holds mode switching, the sidebar holds per-mode lists, the main pane holds the editor, the new statusbar holds system state. Tabs cohere visually into their panes, empty-states are uniform across every surface, and a sharedrenderDrawerprimitive backs Assistant / Help / Tests / Activity / future Inspector — drawer chrome is no longer hand-rolled per surface. Single-Accent + Protocol-Glyph is the only colour encoding; sharper radii (2/4/6 px) come from CSS custom properties. Sidebar means navigation; URL/Schema-Files/AI-Settings became their own surfaces.Workspace = project folder (#147–#151 + #196 Phase 2)
bowire workspace init / export / import / migrate-formatmakes a workspace a real directory you can commit. Per-entity files (one JSON per request / environment / collection / recording) survive merges; secrets live in a siblingsecrets/tree that's.gitignored by default. TheKuestenlogik.Bowire.Workspace.Gitruntime (shipped in this release) plumbs the per-entity layout through the workbench at read + write time, watches the directory for external edits viaFileSystemWatcher+ SSE so the workbench reload-toast fires when a teammate commits over your shoulder, merges<env>.jsonwith its<env>.secrets.jsonsibling at resolve-time so the secret split stays a load-time concern instead of a save-time worry, and gates concurrent edits across two open Bowire instances via a stale-pid-aware.bowire.lock. For disk-mode workspaces (recordings / collections / scripts live on disk rather than inlocalStorage) the newworkspace export <file.json>+workspace importCLI verbs capture every per-entity file in a single archive —.bww-style state download stays available for browser-mode workspaces.Workspace integrity — plugin pins + scope-split settings (#193)
A workspace can now pin the protocol plugins it expects (
workspace.pluginPins: { rest: ">=2.0", grpc: "*", mqtt: "5.x" }). When a team member opens the workspace, a banner fires if any pinned plugin isn't loaded — with "Install all" and "Open editor" actions instead of cryptic "no such protocol" errors at first request. The pin editor lives in the workspace's own Settings tab, so pins ride the workspace into git instead of getting buried in per-user state. The Settings dialog itself grows a scope-split tree: "My preferences" (per-user — Assistant config, theme, shortcuts, plugins) vs "This project" (per-workspace — pins, sources, env-inclusion, AI override). The Assistant tab supports per-workspace overrides directly: a scope chip in Settings, a matching reminder chip on the workspace surface, and one-click "Use global instead" to drop the override.Optional packages live outside core
Core
Kuestenlogik.Bowireships with zeroPackageReferenceentries — only theMicrosoft.AspNetCore.Appframework reference. Embedded hosts add only what they actually use:Kuestenlogik.Bowire.Extension.MapLibre→Kuestenlogik.Bowire.Map— the v1.3.0-rc.1 of the MapLibre extension will be deprecated + unlisted on nuget.org after 2.0 ships (#197).Kuestenlogik.Bowire.Telemetry— embedded hosts that don't want self-observability no longer pull the OTel transitive weight. The standalone CLI keeps--telemetryworking because the tool transitively references it..Ai,.Helpstay opt-in as before. Standalonebowirebundles them.Naming convention going forward — optional first-party packages are
Kuestenlogik.Bowire.<feature>(.Ai,.Help,.Telemetry,.Map) orKuestenlogik.Bowire.<area>.<backend>(e.g.Kuestenlogik.Bowire.Workspace.Git, shipped in this release). The legacy.Extension.*prefix isn't used for new packages.OpenAPI library decoupled via adapter packages
REST plugin no longer takes a hard dependency on
Microsoft.OpenApi. A newIBowireOpenApiAdapterseam inKuestenlogik.Bowire.Protocol.Restlets the consumer pick the library version:Kuestenlogik.Bowire.Protocol.Rest.OpenApi2— pinsMicrosoft.OpenApi2.x, matches what ASP.NET Core 10'sAddOpenApi()transitively pulls. Standalonebowirebundles this one.Kuestenlogik.Bowire.Protocol.Rest.OpenApi3— pinsMicrosoft.OpenApi3.x for hosts that want the modern grammar.Both can be loaded side-by-side; the adapter registry auto-picks the one matching the runtime's
Microsoft.OpenApimajor. Resolves the OpenAPI-DLL-version conflict reported on .NET 10 hosts running side-by-side with ASP.NET's bundled discovery.Across-the-pane omnibox (#124 / #162)
Cmd/Ctrl+K opens a single search line that ranks methods, recordings, collections, settings, and
?-prefixed AI prompts uniformly. Replaces the per-surface searches that used to live in the sidebar, drawer, and method picker.Action log + Ctrl+Z (#168) and hint dismiss (#169)
Every destructive action (delete recording, delete collection, delete workspace, swap environment scope) is reversible from the Activity drawer or via Ctrl+Z. Hints carry a permanent dismiss key that lands them in Settings → Hints and warnings so the user can restore one without restarting.
Workspaces tree + per-plugin DisplayName (#192 / #167)
Sources, collections, recordings, and environments all live as nodes under the Workspaces tree on the left rail. Plugin Settings reads each plugin's
DisplayNamefrom its registration so the row labels match what the plugin author calls itself (no more raw assembly-name fallback).Recordings as portable artefacts —
.bwrformat +bowire mock <recording.bwr>(#210 / #211)Recordings get a standalone, self-contained file format. A
.bwris a single JSON archive that carries every step of a captured session — protocol metadata, request/response pairs, content-addressed bodies, timing — without depending on a workspace it was authored in. Drop one on a colleague's machine and it loads cleanly even when their workspace pins a different plugin set.... (truncated)
1.9.0
Highlights — Tier 4 of the security roadmap lands
Bowire's product positioning has been "Burp Suite for the non-HTTP protocols, with schema-awareness, self-hosted, with AI-assisted threat modeling via MCP." v1.9 closes the AI-assisted half of that promise — every discovered API surface in the workbench can now be analyzed by an LLM that grounds itself in the actual schema + traffic, not generic web knowledge.
appsettings.jsonedits, no restart.The roadmap calls this Tier 4. Tiers 1–3 (record-as-attack, fuzz UI, MITM proxy) shipped through v1.4.x; Tier 5 (auto-exploit / proof-of-vulnerability) is its own framing and a different risk posture, deliberately out of scope here.
Also in this release
The 94 commits since v1.8.0 carry a lot more than the marquee. Highlights of the supporting work:
Security as a first-class drawer, with a tier that doesn't need AI (#111 + #112)
Ctrl/Cmd+Shift+S). The AI drawer stays focused on conversational assistance (hints + chat). Mental model: AI = assistant, Security = scanner / analysis.ThreatHeuristicin core): verb-based mutation scoring, BOLA-pattern detection on path params, admin / auth / PII path matching, anonymous-auth bumps, sensitive-field-name detection in the input shape. Sub-millisecond per endpoint. Each ranked row carries aruleTraceso users can audit which rules fired against which endpoint.AI assistant — full MCP-style tool calling (#89, #108, #109)
Microsoft.Extensions.AIAIFunctions available on every chat request:bowire_list_services,bowire_describe_method,bowire_recent_history. The model calls them mid-conversation to drill in. The Ollama path is wrapped inFunctionInvokingChatClientso the tool-call loop actually round-trips. Tool calls render as visible "Consulted X" steps in the chat transcript with collapsible args.bowire_invokeisn't even registered — the model literally cannot try. When ON, the AI dispatches throughprotocol.InvokeAsync(same path/api/invokeuses) and every call writes a JSONL row to~/.bowire/.ai-actions.jsonlfor audit. Toggle is session-only — never persisted to localStorage.bowire_open_methodtool lets the AI navigate the workbench to the right method ("Show mepet.findPetsByStatus" → workbench opens the request pane on it). Always available, no side effects beyond UI state.(N s)counter with a pulsing accent dot + a Cancel button that aborts the fetch — no more wondering whether the request hung.Workbench UX
Ctrl/Cmd+Shift+Ashortcut. Persists across method/service switches. Was a peer of Response/Logs/Code in the response-pane tab strip, which forced you to choose between seeing the AI and seeing the response.API conventions
application/problem+jsonwith stabletypeURNs (urn:bowire:ai:model-not-found,urn:bowire:discovery:no-match, …), structureddetail, and typed extensions per error class. Backward-compatible: every body still carries anerrorfield set to the title so legacy readers degrade gracefully.ollama pull Xor pick a different model in Settings → AI", with alinks: [{rel: configure}]extension pointing back at the settings page.Bug fixes
lockServerUrl=false.el()helper coercedundefinedattribute values to the literal string"undefined", which the browser treats as truthy.--urlwas falling back to embedded UI mode because the heuristic checkedserverUrls.lengthinstead of trustingconfig.embeddedMode.[]even when a runtime URL was passed via the sidebar.Task.WhenAll+ a 8 s per-probe ceiling.method.source === 'grpc'.Docs
... (truncated)
1.8.0
Highlights
AI side-panel (#25 — Phase 1 + Phase 2)
The workbench learned to think. Phase 1 ships a deterministic hint engine that runs entirely without an LLM — fifteen rules that read live workbench state (selected method, last response, recordings, protocol, mock count) and surface contextual hints in a new side-panel slot. Phase 2 ships the optional
Kuestenlogik.Bowire.AiNuGet: aMicrosoft.Extensions.AIIChatClientseam backed by OllamaSharp, auto-detect for Ollama on127.0.0.1:11434+ LM Studio on:1234, three endpoints (GET /api/ai/probe-local,GET /api/ai/status,POST /api/ai/chat), and CLI flags--ai-provider/--ai-endpoint/--ai-model. The standalonebowireCLI bundles the package; embedded hosts opt in by adding it. AI Settings UI (#63) lands the in-workbench picker for provider / endpoint / model — switching providers no longer needs a restart, persistence rides onIBowireUserStore, and embedded hosts that supply their ownIChatClientwin cleanly with a "host-managed" status badge. Findings triage (#61) adds a?button next to every Vulnerable row in the fuzz panel that asks the model "is this real, and how do I fix it?" — colour-coded confidence score, suggested fix, in-memory cache. Outbound calls stay opt-in (probe only touches loopback, chat only goes where you point it).Workbench mocks (#56 + #57)
Mocks finally have a UI. The new
MockRegistry+/api/mockssurface lets the workbench start mocks from any recording with one click, list them in the sidebar, and stop them without dropping to a terminal. #57 adds a per-mock request log: every inbound call lands in a bounded ring buffer that the workbench tails live, so you can see exactly which step matched which incoming request and which ones missed. Backed by anIMockRequestObserverSPI so external observers (metrics emitters, tracers) can plug in.Auth seam (#28 Phase A + #28 Phase B + #31 + #32)
The first real multi-user foundation. #31 adds the
IBowireAuthProviderSPI so plugins can wire authentication schemes + a default authorization policy, and adds aConfigure(IApplicationBuilder)hook + theUseBowireAuth()middleware so providers can mount callback paths / claims-transformation. #32 ships the OIDC plugin's required-claim filter and session-token forwarding for downstream service calls. #28 Phase A + B introduce theIBowireUserStoreseam and migrate every per-user store onto it (EnvironmentStore,RecordingStore,CollectionStore,FlowStore,PluginManager,PluginUpdateCheckService, schema-hints, the new AI config file) — single-user installs keep the legacy flat~/.bowire/layout, multi-tenant deployments swap in a per-identity resolver once SCIM lands.Self-telemetry (#29 — Phase 1 + Phase 2)
Bowire can now observe itself. Phase 1 ships the
BowireTelemetryseam — a canonicalActivitySource+MeteronKuestenlogik.Bowirewith pre-declared instruments (bowire.invoke.count,bowire.invoke.duration,bowire.discover.count,bowire.plugin.load,bowire.mock.requests) — plus an opt-inAddBowireTelemetry()that wires OpenTelemetry against them. Phase 2 plumbs the instruments through the discovery loop (per-protocol probe counts + outcomes), the plugin scan (loaded vs disabled), and the mock pipeline (per-request counter with method / outcome / status tags). Operators opt in via--telemetry/Bowire:Telemetry:Enabled=true; OTLP endpoint / headers come from standardOTEL_EXPORTER_OTLP_*env vars. Bowire.Samples ships a Grafana 11 dashboard (Bowire.Samples/dashboards/bowire-overview.json) that reads non-zero panels from day one.Collections (#30)
Postman-style named groups of saved requests, sequenced against the active environment. Backend persistence routes through the new
CollectionStore(single-user installs land at~/.bowire/collections.json, multi-tenant routes per identity viaIBowireUserStore), and the new flow-to-collection export turns any saved flow into a runnable test suite.Plugin lifecycle in the workbench (#27)
The plugins panel got an Inspect button + modal so you can see version, metadata, and recent activity for any installed plugin from the workbench instead of running
bowire plugin listin a terminal. Pre-release support flows through the daily update check + the install path.Multi-repo release cascade
The release pipeline now discovers sibling repos dynamically by querying the Kuestenlogik org for repos carrying the
bowire-cascadeGitHub topic — adding a new sibling to the cascade is now opt-in via that repo's own Settings → Topics, no PR against the main release workflow required. Cascade templates live in.github/sibling-templates/. Auto-PR + auto-merge use the org's rebase-only convention.Maintenance
post-release-floor-bump.ymlworkflow auto-bumpsDirectory.Build.propsto<just-released>-devafter every successful release, opens a PR, no hand edit required.GeneratedRegexonExcludeByAttributeso the source-generator-emitted Regex partials no longer drag the line-coverage denominator.cs/log-forgingalert closed (#40) — defensive CR/LF scrub before logging mock IDs / recording display names.<code>in the dev-loop-debugging hero, fixed the protocol-search input stacking the tag prefix, refreshed stale "planned" marks on the MCP comparison.BOWIRE_DISPATCH_TOKEN.Full Changelog: Kuestenlogik/Bowire@v1.7.0...v1.8.0
1.7.0
Highlights
Four new protocol plugins
Kuestenlogik.Bowire.Protocol.Nats— pub/sub + req/reply (Phase 1) + JetStream + Services API (Phase 2). Sits on the official NATS.Net 2.x client.Kuestenlogik.Bowire.Protocol.JsonRpc— JSON-RPC 2.0 over HTTP and WebSocket.Kuestenlogik.Bowire.Protocol.Pulsar— Apache Pulsar producer / consumer / reader.Kuestenlogik.Bowire.Protocol.Soap— WSDL discovery + envelope construction.gRPC: Connect Phase 2
Server-streaming over
application/connect+protois in. Connect-Web clients now talk to a Connect-mode Bowire workbench for streaming methods, not just unary.Mock-as-stand-in
Recordings now carry the source schema verbatim.
bowire mock --recording <file>re-emits/openapi.json(REST) and/asyncapi.yaml(messaging) so peer Bowires pointed at the mock discover the full original contract, not just the replayed slice.bowire export ... --recording <file>annotates each operation withx-bowire-coverage: { recorded, stepCount }so consumers see the replay gap explicitly.bowire exportCLINew
openapi/asyncapisubcommands that materialise the discovered contract as a YAML / JSON file on disk — useful for diff-against-prod and contract-test pipelines, especially for messaging protocols where hosts don't render an/asyncapi.yamlthemselves.AsyncAPI
AsyncApiDocumentBuilderemits AsyncAPI 3.0 from any discovery result.NatsBindingResolverdispatchesbindings.natsoperations to the NATS wire plugin.Tool I/O refactor (Phases 1-3 complete)
Every CLI command path now flows through the
BowireCliIotype instead of directConsole.Outwrites. Output is structured, testable, and pipe-friendly —bowire scan --json | jqworks the way you'd expect on every subcommand.Bootcamp launched on bowire.io
The Bowire Bootcamp — six units plus a capstone — is wired into bowire.io. Two parallel setup tracks (CLI / Embedded), then shared lessons on recording / mocking / MCP / plugin authoring / CI. The capstone weaves the lot into a single end-to-end Harbor-Tour scenario.
Maintenance
What's Changed
Full Changelog: Kuestenlogik/Bowire@v1.6.1...v1.7.0
1.6.1
Highlights
IBowireAuthProviderSPI plus an OIDC provider implementation (roadmap "Up next #1").BowireMcpResourcesandBowireMcpPromptsimplementations and matching coverage.Notes
The plugin-update check is opt-in: outbound network calls remain off until you flip the setting on. Auth-provider plugins implement the new
IBowireAuthProviderSPI; the bundled OIDC provider is the reference implementation.Full Changelog: Kuestenlogik/Bowire@v1.6.0...v1.6.1
Commits viewable in compare view.
Updated Kuestenlogik.Bowire.Protocol.Rest from 1.6.0 to 2.1.1.
Release notes
Sourced from Kuestenlogik.Bowire.Protocol.Rest's releases.
2.1.1
<One-sentence frame for what 2.1 is about. Replaces this placeholder
the moment the first 2.1 work lands.>
Highlights
Bowire as a transparent in-process interceptor —
app.UseBowireInterceptor()(#153)The new interceptor middleware extends Bowire from "the operator drove a call" to "every request flowing through the host."
app.UseBowireInterceptor()registers a pass-through middleware that records method / path / headers / request body / response status / response headers / response body / latency for every request the host receives — from any client, with zero client-side setup, no cert trust, no separate process. Captured flows land in the workbench's new Intercepted rail (sister to the standalone Proxy rail) live over SSE. When the operator starts a recording in the workbench, intercepted flows auto-append as recording steps — point any client at the host, click stop, replay. Standalone reverse-proxy mode (Phase C) and mock injection (Phase D) ship in later releases.MCP-over-MCP forwarder —
bowire mcp serve --attach(#286)A thin Bowire process can now relay every incoming MCP tool call to a heavier Bowire running on the operator's workstation.
bowire mcp serve --attach localhost:5198 --port 5199boots a forwarder that surfaces no local tools —tools/list,tools/call, prompts, resources, and resource templates are all marshalled to the parent and the parent's response is relayed verbatim. Useful when an LLM agent on a CI runner / container should drive the workstation Bowire without sharing the parent's MCP socket directly. The parent gains a matching--token <secret>bearer-auth gate (--bind httponly); the child passes the secret with--attach-token <secret>.Workspace-delete Undo decoupled from Trash (W2a)
The action-log entry for
workspace-deleteis now self-contained: it carries the full snapshot (workspace,data,originalIdx) inline so Undo reads from the entry itself instead of looking the entry up inworkspacesTrashat undo-time. This gives the two surfaces independent retention models:bowire_trash_retention_days(W2).Hard-delete (W2 mode) now writes ONLY the action-log snapshot — there's no trash entry to consult. Soft-delete writes both. Entries persisted BEFORE this change still resolve via the legacy Trash-lookup path (a one-shot
console.infoflags the fallback so the migration window is visible).The other entity-delete resolvers (
recording-delete,flow-delete,env-delete) were audited and already carry their entity payload inline — onlyworkspace-deletehad the Trash coupling.Settings tree organized by scope; Configure + Plugins merged (#325)
The Settings dialog now exposes scope through the parent-node names:
This machine(localStorage / install-scoped) andWorkspace…(.bww-scoped, travels with the workspace file). The per-page disclaimer that used to repeat the scope copy on every sub-page ("These settings stay on this machine — they don't travel with the workspace file (.bww).") is gone — the tree's grouping carries that information unambiguously. The standalonePluginslifecycle leaf is gone; it has merged withConfigureinto a singlePluginsnode whose six sub-pages (Protocols / UI Widgets / Modules / Formats / Tools / Discovery providers) now render the inline per-plugin settings AND the lifecycle button cluster (Restart / Unload / Reset storage, wired to the existingPOST /api/plugins/{id}/lifecycle/{action}501-stub) per row, plus Install + Check-for-updates at the top of the Protocols sub-page. A new empty-stateWorkspace… → Per-Workspace overridespage surfaces every machine-scoped setting that the active workspace has overridden (today: the AI provider config, when the workspace has its ownai-config.<workspaceId>.json); saved deep-links from v2.1 (configure-protocols,plugin-<id>,extension-<id>) keep working unchanged, and any saved value pointing at the droppedpluginslifecycle id migrates toconfigure-protocols.Breaking changes
Mocks + Traffic rails merged into a single Intercept rail
The Mocks rail and the Traffic rail (which itself unified the earlier Proxy + Intercepted rails) have collapsed into one Intercept rail with four sub-tabs in a locked order:
UseBowireInterceptor()(was Traffic → "Flows").The merge eliminates the previous Phase-3 rail bloat where Mocks + Traffic + the already-hidden Intercepted + Proxy descriptors competed for the same conceptual surface ("what do I do with live traffic"). It also disambiguates "Flows" — the orchestration rail keeps the name; what Traffic used to call "Flows" is now "Captured".
Migration is automatic at first paint (idempotent). On boot,
prologue.js:... (truncated)
2.1.0
v2.1 turns Bowire from a discovery + invoke workbench into a real composition surface. The new Compose rail carries a Hoppscotch-style request builder with a protocol picker, per-protocol layouts, history persistence, binary uploads, and full Collections + Presets integration. Underneath, the workbench is now pluggable: rails and modules ship as package contributions, so the standalone Tool, embedded
MapBowire(), and operator-built distributions can pick exactly the surface they want. The new interceptor middleware lets a host hand Bowire every inbound request without client setup. A MapLibre extension + a stand-alone TacticalApi sample demo coordinate-bearing payloads on a live map with bi-directional JSON↔map sync. Streaming subscriptions are now legible, the JSON viewer reaches Hoppscotch parity, and the guided tour walks first-time operators through every rail.300+ commits since v2.0.1. Three packaging breaking changes for embedded hosts: the standalone
Kuestenlogik.Bowire.Rail.Collectionspackage is retired, the wholeRail.package prefix dropped (e.g.Rail.Compose→Compose,Rail.Benchmarks→Benchmarking), and the interceptor surface (Proxy + Intercepted + Traffic rails + the middleware that lived in Core) consolidated into a singleKuestenlogik.Bowire.Interceptorpackage. See Breaking changes below for the one-to-one mapping table. Existing workspaces, collections, recordings, benchmarks load identically; operator-savedrailMode/ enabled-rails state migrates on first boot.Highlights
Compose rail (#293, #289, #290, #291, #295)
The old Design rail is rebranded and rebuilt as Compose — a single-line Hoppscotch-style request bar at the top, per-protocol layout below, history + collections + presets on the side. The protocol picker switches the layout in place: REST gets a URL + KV-table chrome, gRPC gets service / method / JSON body, MCP gets tool / arguments, MQTT gets topic / QoS, WebSocket / SSE get connect / subscribe shells. History persists across reloads, binary uploads ride a base64 side-channel through the wire, and benchmarks can re-run any historical request directly. A Compose tab supports right-click → Duplicate tab so you can fan out a request without losing the original. The toolbar lives where you'd expect (no toolbar in Raw mode, of course).
Pluggable workbench — rails + modules as package contributions (#294)
Bundle.Workbench is now a meta-package: every rail, every module, every extension is a separate project that registers itself via
[BowirePlugin]/[BowireExtension]attributes. The standalone Tool depends on Bundle.Workbench; embedded hosts can drop the bundle and pick per-package references for a smaller surface (e.g. just REST + Compose without the AI module). Bundle.Minimal carries the Core + Home + Discover only — useful for "tiny embedded probe" deployments. Settings → Plugins now lists every loaded protocol AND every UI extension with kind / capability chips so the operator can see what's installed at a glance.Transparent in-process interceptor (#153)
app.UseBowireInterceptor()registers a pass-through middleware that records method / path / headers / request body / response status / response headers / response body / latency for every request the host receives — from any client, with zero client-side setup, no cert trust, no separate process. Captured flows land in the workbench's new Intercepted rail live over SSE. When the operator starts a recording, intercepted flows auto-append as recording steps — point any client at the host, click stop, replay.MapLibre extension + TacticalApi integration (#new)
A new
Kuestenlogik.Bowire.Mapextension auto-mounts a MapLibre GL JS viewer whenever a response carries thecoordinate.wgs84semantic kind. The Wgs84CoordinateDetector picks up{lat, lon},{latitude, longitude}, AND{latitudeCoordinate, longitudeCoordinate}shapes (TacticalAPI naming) anchored by anchored case-insensitive regex. Bidirectional sync: hover on a JSON{lat,lon}block highlights the matching map pin; hover on a pin highlights the JSON. Click on a pin scrolls the JSON to the line and auto-expands collapsed ancestors. Right-click on a coordinate offers Center on map; double-click on either side copies the path to clipboard. A right-side gutter hint surfaces the semantic kind on hover (wgs84 coordinate).The new Sample.TacticalApi server (separate
samples/project) hosts Rheinmetall'sSituationgRPC service with eight NATO-phonetic-callsign tactical entities (Alpha-1 Recon UAV, Bravo-2 Air Defence Btry, …) drifting on a per-object sine-wave so subscriptions feel live. Bundle.Workbench ships theKuestenlogik.Bowire.Protocol.TacticalApiplugin out of the box.Streaming subscriptions, finally legible (#new)
The action button adapts to the active method type: Execute for unary, Subscribe for server-streaming (changes to Stop while a stream is live), Connect / Disconnect for bidirectional and client-streaming. A live state badge in the response pane shows
● Subscribed — 0 msgs→● Receiving — 42 msgs→○ Idle — 42 msgsafter 5 s without a frame →○ Closedon stop →× Erroron stream failure. A statusbar pill lists every active subscription across methods; click → dropdown with switch / stop / copy-path / "stop all". The action button keeps a stable footprint so layout doesn't jitter when methods change.Hoppscotch-parity JSON response viewer + toolbar (#302, #new)
The response viewer renders one JSON line per row with a sticky left gutter carrying line numbers AND the collapse chevron — chevrons line up on the same vertical column regardless of indent depth. Click anywhere on an opener line OR the gutter chevron to toggle. Click = toggle, double-click = Copy path, right-click = unified menu with
Copy ${response.X},Copy path, plus extension-contributed items (Center on mapwhen the map plugin resolves the target). A dedicated JSON toolbar — Expand all, Collapse all, Wrap long lines, Search (Ctrl/Cmd+F), Copy response, Download — sits above the viewer and only renders when the JSON tab is active in tab mode (so the map widget gets its own toolbar real estate). Expand / Collapse rebuild the viewer in place — no full render, so the map's WebGL canvas survives.Tab ↔ Split layout for response viewers (#new)
Server-streaming and unary response panes get a tab-strip with JSON + per-extension widget tab + a layout toggle. Click the toggle → split-pane with JSON on one side, widget on the other; click again → tabs. Per-method layout persists in localStorage so the operator's preference for each method is remembered. The split-layout decision is extension-driven — Core asks the framework
preferredSplitExtensionForMethod(svc, method)rather than hard-coding thecoordinate.wgs84kind. Layering stays clean: Map-specific code inKuestenlogik.Bowire.Map, Core stays generic.Guided tour — page-navigation, alternative paths, per-rail empties (#281, #303)
A spotlight-overlay tour engine walks first-time operators through every rail: workspace creation, source-URL add, method invoke, recording, collection composition, flow building, traffic capture, security scan. Each rail's empty state surfaces its own secondary tour. The tour engine handles dialog-modal yields, alternative paths (e.g. operator already has a workspace), advance modes (
on-cta/on-event/next-button), ...Description has been truncated