2026.11.1 — 2026-11-02
Breaking
Browse a stream, send to an exchange and purge a queue on a cluster read as one (5be68594)
A stream is read as a one-partition log by offset, and reading never removes a message. A classic or quorum queue is refused before the broker is read, with the driver's own reason (409 unavailable-on-kind). A send takes an optional routingKey to an exchange; one no queue received is a 409 not-routed naming the exchange and the routing key, and nothing is stored. A purge of a queue on a cluster read as one runs over the whole cluster by its id, with the ready messages as its estimate, and the dry run says what the etag holds (identityBasis). A backlog that is only an estimate says its counters are sampled when the system gives no other reason. A bulk purge of such a queue runs once for the cluster.
Change a cluster read as one as one (a1040808)
A cluster whose nodes have no management URL (Kafka, RabbitMQ) is changed as a whole through its driver, by resource id, instead of failing with "no node with a management URL". The shared delete of a subscription or destination, the create of either, and the bulk delete run the driver's preview (estimate and etag basis) and then execute under the etag they just previewed; a run whose etag moved is refused as stale (412). Artemis keeps its per-node path and partial outcomes. The lifecycle outcome now says what its etag holds (identityBasis), and an approver is told when the system cannot tell a recreated resource apart. Plugin message sources of such a cluster are read once for the cluster.
fix(kafka): a Kafka topic is now created and deleted from the shared destination screens and routes, which refused it before.
Added
Create a destination from the Destinations view (339ea029)
A New destination action opens the cluster system's own create form where it contributes one, and is disabled with the reason where none of its destination kinds can be created.
Manage a RabbitMQ cluster's nodes, virtual hosts, bindings, policies, permissions and shovels (ce0db74d)
A RabbitMQ cluster now has its own views: nodes with their alarms and partitions (its landing page), bindings, shovels and federation links, virtual hosts, policies and permissions. Every change is previewed first with its effect, and removals are confirmed by press-and-hold. A policy preview lists the names it matches, as Rahdar matches them, and those a policy of higher priority wins.
The subscription drawer shows a queue's type, leader, members, arguments and effective policy. An exchange can be published to, with its routing key and headers, and a message no binding routes is reported inline. Queues and exchanges are created from forms that explain each type.
Register a RabbitMQ cluster from its management URLs (4d1d48c2)
The registration page now offers a RabbitMQ form: management URLs, optional AMQP endpoints, a user name and password or a bearer token, a TLS bundle for encrypted addresses, and the event vhost and watch interval under Advanced. Addresses are shown as the entries they parse to, with default ports, and an account in a URL is refused. The connection check lists every management URL and AMQP endpoint it tried with its outcome and cause, names the cluster ("Cluster name"), and explains wrong-endpoint and unreachable-data failures. A RabbitMQ node is shown by its id (rabbit@host). The cluster's connection settings can be edited, and the secret is asked for again when the URLs, endpoints, user or kind of credential change.
Show RabbitMQ clusters through the shared screens (9e166dc0)
A queue kind that cannot be browsed says why instead of reading, and a stream is read as one log with no partition to choose. Delete and purge confirmations say when the system cannot tell a recreated resource apart. Send takes an optional routing key and names it when nothing is bound for it. Systems can contribute their own create-subscription form.
Read a RabbitMQ cluster's nodes, virtual hosts, bindings, policies and permissions (aeb72d73)
Adds six read-only tools for RabbitMQ clusters: rabbitmq_nodes, rabbitmq_list_vhosts, rabbitmq_list_bindings, rabbitmq_list_policies, rabbitmq_list_permissions and rabbitmq_list_shovels (shovels and federation links, addresses without credentials).
Manage a RabbitMQ cluster's virtual hosts, bindings, policies and permissions (4a8eb342)
Adds the RabbitMQ namespace under /clusters/{id}/rabbitmq/: nodes with their alarms and partitions, virtual hosts, queue and exchange creation, bindings, policies, users, permissions and topic permissions, shovels and federation links. Every change to a virtual host, binding, policy or permission, and the deletion of a shovel, is previewed first (effect, etag and an identity basis of CONFIGURATION), then runs as a gated operation: held for approval where a policy says so, audited before and after, and refused as stale when the resource changed since the preview. A policy preview lists the queues and exchanges its pattern matches and those a policy of higher priority already wins. Shovel and federation addresses never carry a credential.
New permissions namespace:read|write|delete and policy:read|write; the operator holds namespace:read|write and policy:read|write, the viewer the read ones, and namespace:delete and access-rule:write stay with administrators. access-rule:read|write move from the Kafka module to the shared resource permissions under the same ids.
Scrape a RabbitMQ cluster, judge its health and bound a stream as a log (0e821200)
The scrape reads every node in one call, keeps the stored nodes true and retires one the cluster stops listing. It reads the queues in one pass: each is carried by the node that leads or hosts it, a stream shows no backlog and says why, and the replicated queues that lost members are counted for the verdict. Health is CRITICAL for a partition, a memory or disk alarm or a quorum queue or stream without a majority, and a warning for a node not running, an under-replicated queue, unsynchronised mirrors or AMQP endpoints that refuse connections while the management API answers. A cluster that reports another cluster name than the registered one is not read until the connection is checked and saved again. A stream is one log, partition 0, bounded by its first kept message and committed offset.
Register a RabbitMQ cluster from its management API (d203cfd4)
A RabbitMQ cluster can now be registered from its management API URLs and, optionally, its AMQP endpoints. The check reaches every management URL and AMQP endpoint, names each one's outcome and each node's state, and names a failure's cause: DNS, REFUSED, TIMEOUT, TLS, AUTHENTICATION, AUTHORIZATION, UNSUPPORTED_VERSION, WRONG_ENDPOINT when an address answers but is not a management API, and DATA_UNREACHABLE when AMQP endpoints were given and none accepts a connection. The cluster is identified by its cluster name, and the account (password or token) is stored with the cluster's other credentials, never in the connection settings. An edit that changes the URLs, the endpoints or the user asks for the secret again.
New tables rabbitmq_connection and rabbitmq_health: recreate the database (ADR-0192). Module boundaries now cover the system modules in module tests.
Browse a stream, send to an exchange and purge a queue on a cluster read as one (5be68594)
A stream is read as a one-partition log by offset, and reading never removes a message. A classic or quorum queue is refused before the broker is read, with the driver's own reason (409 unavailable-on-kind). A send takes an optional routingKey to an exchange; one no queue received is a 409 not-routed naming the exchange and the routing key, and nothing is stored. A purge of a queue on a cluster read as one runs over the whole cluster by its id, with the ready messages as its estimate, and the dry run says what the etag holds (identityBasis). A backlog that is only an estimate says its counters are sampled when the system gives no other reason. A bulk purge of such a queue runs once for the cluster.
Change a cluster read as one as one (a1040808)
A cluster whose nodes have no management URL (Kafka, RabbitMQ) is changed as a whole through its driver, by resource id, instead of failing with "no node with a management URL". The shared delete of a subscription or destination, the create of either, and the bulk delete run the driver's preview (estimate and etag basis) and then execute under the etag they just previewed; a run whose etag moved is refused as stale (412). Artemis keeps its per-node path and partial outcomes. The lifecycle outcome now says what its etag holds (identityBasis), and an approver is told when the system cannot tell a recreated resource apart. Plugin message sources of such a cluster are read once for the cluster.
fix(kafka): a Kafka topic is now created and deleted from the shared destination screens and routes, which refused it before.
Let a cluster be registered through a RabbitMQ management API (de1e280c)
The registration request, the edit and the connection detail carry a RabbitMQ variant: management URLs, AMQP endpoints, a write-only account or token, a TLS bundle, an event virtual host and a watch interval. The account and token are masked when printed. A check can report every endpoint it tried, and fails with WRONG_ENDPOINT or DATA_UNREACHABLE. Systems are listed with the management-api connection style.
Changed
Merge the SonarCloud sweep (36a4b55e)
Merge P2: the sweep's leftovers (4cc5cd23)
Merge S2: RabbitMQ screenshot sweep and its fixes (ded9be4c)
Merge main into the RabbitMQ support (13bdabdd)
Merge P1: close the RabbitMQ support's gaps (8bfaf519)
Merge B9: RabbitMQ real-broker tests (7ce82a41)
Merge W3: RabbitMQ feature web (3710b672)
Merge W2: RabbitMQ registration web (55f9a7dc)
Merge D1: RabbitMQ docs (aedc822a)
Merge W1: shared web for RabbitMQ (f211e80f)
Merge B8: RabbitMQ MCP read tools (9eae0ba3)
Merge B7: RabbitMQ namespace API (fa971526)
Conflicts:
src/main/java/io/github/sudoitir/rahdar/system/rabbitmq/package-info.java
src/test/java/io/github/sudoitir/rahdar/system/rabbitmq/RabbitMqModuleTest.java
Merge B6: RabbitMQ scrape and health (bffa25e1)
Merge S1: RabbitMQ stacks and seed (dc30430b)
Merge B5: RabbitMQ module core (a11cabac)
Merge B4: messages on a cluster read as one (c1222bf2)
Merge B3: whole-cluster operation path (f46a745c)
Merge B2: RabbitMQ registration contract (2b02bfab)
Fixed
Read versions, URLs and addresses in linear time (5d333bc5)
The supported-version range, the trailing slashes of a management URL, the account stripped from an address in a tool result, and the address fields of the connection form no longer use regular expressions that backtrack on a long input. Each is read by a scan instead, with a test over a very long input.
The RabbitMQ virtual hosts view no longer moves its table when the incomplete-counts notice arrives (f7786542)
The notice that the counts are lower bounds now sits on the toolbar's own row, beside the create action that already sets its height, instead of as a block above the table.
The delete confirmation opens before the cluster has loaded (5fc3ac86)
A RabbitMQ management URL whose host does not resolve says the name does not resolve (c2a8382d)
The connection check reported an unresolvable host as "Connection refused: nothing is listening", because the driver words a connect failure as a refusal even when the host name never resolved. The check now looks for a name that does not resolve anywhere in the failure's cause chain before it considers a refusal, and says so in its message.
The delete confirmation names forward routes only on Artemis and states the identity basis once (c913c3b2)
Deleting a subscription on RabbitMQ told the operator that a forward route into its destination would be removed, wording that only applies where routes forward into a subscription, and showed the note that a recreated resource is not told apart twice. The route sentence is now shown only on an Artemis cluster, and the note appears once, from the preview's identity basis.
Consumer health on RabbitMQ names each queue by its own id, kind and virtual host (7ce622a3)
The consumer-health screen built a subscription's id from its bare name, so on a RabbitMQ cluster every row read "Classic queue", showed no virtual host, and a link could open the queue of the same name in another virtual host. Each row now carries the subscription's real id, kind and name, is labelled with its real kind, shows its virtual host in place of a destination, and links by its whole id. Its rates are read under the key the scrape sampled the queue by, so two queues of one name in different virtual hosts keep their own verdicts.
The consumer-health API returns the subscription's whole id and its name, and its destination is absent for a system whose queues have none. The diagnose tool and the subscription panel look a subscription up by id.
Keep RabbitMQ row actions and the virtual host column at a width that shows them, and hold the federation links until the shovels above have settled (6d3bea60)
The Edit and Delete buttons were cut to "Ed" and "Del", and the federation section jumped when the shovels table above it replaced its loading rows.
Read a RabbitMQ stream's messages page the same before and after the cluster loads (7c17d03e)
The browse controls and the heading height were chosen only once the cluster answered, so the page jumped, and its breadcrumb showed the raw queue id with a percent-encoded virtual host.
Leave the write-uncertainty notice off a log's messages page (e053e797)
The notice about writes arrived late and pushed the toolbar down 200 px on a RabbitMQ stream.
Show an unknown virtual host filter as an empty RabbitMQ list, not as a Not found error (7a2acd53)
Filtering policies, bindings, permissions or links by a virtual host the broker does not know ended in an error page.
List channels and connections for a read-only account on a RabbitMQ cluster (45684604)
The list asked for producers to count them, and RabbitMQ has none, so a caller without the right to read every connection was refused with a conflict.
Keep the cluster registration buttons whole beside a long reason (d0a6c790)
Check connection and Register cluster were cut off when the sticky bar's reason wrapped.
Focus the name, not the virtual host list, when creating a RabbitMQ queue or exchange (b619a6ac)
The virtual host list opened on focus and covered the name field.
Stop describing a RabbitMQ stream in terms of partitions and consumer groups (c0937867)
The stream's messages page told the operator to browse by partition and showed a consumer group position that a stream does not have.
Name the virtual host in the RabbitMQ subscription and destination lists, and read queue references without percent signs (55cf3e9e)
Two queues or exchanges of one name in different virtual hosts could not be told apart, the panel title started with a stray slash and the messages page showed %2F.
Act on a queue by its full id, so RabbitMQ queues can be deleted, edited and paused from the subscription screens (f8b55db9)
The lifecycle calls rebuilt the id from the name alone, which dropped the virtual host: deleting a RabbitMQ queue was refused with "named by 2 id segment(s), not 1". A queue whose kind cannot be paused, edited or deleted now shows the reason instead of an enabled button.
Show every row action of a RabbitMQ virtual host, policy and permission (697d4eb5)
The second button of the Change column (Delete, Clear) was stacked under the first and clipped by the row, so it could not be seen.
Show a RabbitMQ queue's members and sync state in its detail (043ff2cc)
A queue on a system without per-node settings is now read from the resource itself: its attributes and its placements (node, role, in sync) are returned on the queue configuration, and the queue panel lists the replicas from them. The effective policy is shown only when the broker reports one.
List a queue that has no destination, named by itself (5eb809f8)
A subscription list answered 500 for RabbitMQ queues, which are fed through exchanges and bind to no destination, and named each queue after its virtual host. A subscription's destination is now optional, a queue in a virtual host is named by the queue, and the outcome of a change to a whole cluster names no node.
Refuse an operation a kind does not have with a conflict, not a bad gateway (ae632a75)
Purging a RabbitMQ stream answered 502 "Unexpected broker response" although the broker was never asked. It now answers 409 unsupported-on-kind with the driver's reason.
Name the namespace's change views apart from the settings preview (b97afc7a)
The OpenAPI description names a schema by its class, so the RabbitMQ change preview, result, effect and diff views took the names of the settings preview and replaced its description. They now carry the RabbitMQ prefix.
Bound a stream by the messages it holds when it reports no committed offset (0a159b5d)
RabbitMQ 4 does not report a stream's committed offset through the management API, so a stream that held messages looked empty. It now ends at its first message plus the messages it holds.
Page a log by the position of its last message, not by parsing the driver's cursor (f8fefd5f)
The driver's cursor token is opaque, so a log's next page now starts one past the last message returned, which also reads forward across the gaps compaction leaves. A token that is not a partition and offset no longer fails the browse.
Security
Bound the matching of a policy's pattern in its preview (8c81fe98)
A policy's pattern comes from whoever may write policies on the broker, and its preview matched it against every queue and exchange name with no limit, so a pattern that backtracks without end could hold a request thread. A preview now spends at most 250 ms on the policy's own pattern and refuses to preview one that needs more; a rival policy whose pattern runs out of its short budget is left out of the comparison.
Run the RabbitMQ driver on amqp-client 5.37.0 (6b38c9fc)
Spring Boot's dependency management pinned amqp-client to 5.30.0, below the version the RabbitMQ driver is built and tested with and affected by GHSA-68mj-5wr7-6fgg and GHSA-93j5-89vc-pph4 (fixed in 5.33.1). The image now carries 5.37.0.