@rahdar/plugin-sdk 2026.10.51 → 2026.10.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package.json +3 -3
  2. package/peers.json +2 -2
  3. package/types/kernel/actions/types.d.ts +35 -34
  4. package/types/kernel/api/paging.d.ts +5 -2
  5. package/types/kernel/api/request.d.ts +2 -2
  6. package/types/kernel/api/resourceId.d.ts +32 -0
  7. package/types/kernel/api/schema.d.ts +1478 -1720
  8. package/types/kernel/approvals/columns.d.ts +1 -1
  9. package/types/kernel/auth/api.d.ts +3 -3
  10. package/types/kernel/auth/useCan.d.ts +8 -8
  11. package/types/kernel/feature.d.ts +8 -2
  12. package/types/kernel/keyboard/useKeySequences.d.ts +3 -2
  13. package/types/kernel/nav/currentView.d.ts +5 -4
  14. package/types/kernel/registry.d.ts +3 -2
  15. package/types/kernel/routing/roots.d.ts +4 -1
  16. package/types/kernel/routing/search.d.ts +7 -0
  17. package/types/kernel/shell/CommandPalette.d.ts +1 -1
  18. package/types/kernel/shell/HomeView.d.ts +1 -5
  19. package/types/kernel/shell/lastPlace.d.ts +1 -1
  20. package/types/kernel/shell/useClusterSystem.d.ts +11 -0
  21. package/types/kernel/slots.d.ts +28 -23
  22. package/types/sdk/index.d.ts +2 -2
  23. package/types/ui/ConfirmDialog.d.ts +3 -3
  24. package/types/ui/DescriptionList.d.ts +1 -1
  25. package/types/ui/EmptyState.d.ts +1 -1
  26. package/types/ui/HoldToConfirm.d.ts +2 -2
  27. package/types/ui/LoadingState.d.ts +1 -1
  28. package/types/ui/NodeOutcomeSummary.d.ts +1 -1
  29. package/types/ui/Toolbar.d.ts +1 -1
  30. package/types/ui/capabilityGate.d.ts +7 -6
  31. package/types/ui/notify.d.ts +1 -1
  32. package/types/ui/table/DataTable.d.ts +1 -1
  33. package/types/ui/table/columns.d.ts +9 -0
  34. package/types/ui/table/index.d.ts +1 -1
@@ -3,7 +3,7 @@ import { type HeldDisplayRow, type HeldOperationSummary } from './api.ts';
3
3
  /** A value as the change table shows it: a secret says it is hidden, and an absent value says which absence. */
4
4
  export declare function valueText(value: string | null | undefined, absent: string): string;
5
5
  /**
6
- * Whether the rows only name what the request acts on (a queue, a user) rather than change values: every row
6
+ * Whether the rows only name what the request acts on (a subscription, a user) rather than change values: every row
7
7
  * lacks a current value. Those read as a list of facts; rows with a current value read as a change table.
8
8
  */
9
9
  export declare const namesTargets: (rows: readonly HeldDisplayRow[]) => boolean;
@@ -19,7 +19,7 @@ export declare const keys: {
19
19
  export declare const accessKeys: {
20
20
  all: readonly ["access"];
21
21
  of: (clusterId?: string) => readonly ["access", string];
22
- resource: (clusterId: string, kind: string, name: string) => readonly ["access", "resource", string, string, string];
22
+ resource: (clusterId: string, type: string, name: string) => readonly ["access", "resource", string, string, string];
23
23
  };
24
24
  /**
25
25
  * What the signed-in user holds, globally or on one cluster, as the server's resolver decides it: through role
@@ -53,8 +53,8 @@ export declare function accessQuery(clusterId?: string): import("@tanstack/query
53
53
  teams: components["schemas"]["TeamMembership"][];
54
54
  createPatterns: components["schemas"]["CreatePatterns"];
55
55
  }, Error>;
56
- /** What the signed-in user may do with one queue or address: the actions they hold on it, as the server decides. */
57
- export declare function resourceAccessQuery(clusterId: string, kind: 'QUEUE' | 'ADDRESS', name: string): import("@tanstack/query-core").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<{
56
+ /** What the signed-in user may do with one subscription or destination: the actions they hold on it, as the server decides. */
57
+ export declare function resourceAccessQuery(clusterId: string, type: 'SUBSCRIPTION' | 'DESTINATION', name: string): import("@tanstack/query-core").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<{
58
58
  actions: string[];
59
59
  }, Error, {
60
60
  actions: string[];
@@ -1,10 +1,10 @@
1
1
  /**
2
- * A queue or address of a cluster, for a check on one resource. Pass the `allowedActions` a row already
2
+ * A subscription or destination of a cluster, for a check on one resource. Pass the `allowedActions` a row already
3
3
  * carries from the server to answer from it with no request.
4
4
  */
5
5
  export interface ResourceWhere {
6
6
  clusterId: string;
7
- kind: 'queue' | 'address';
7
+ type: 'subscription' | 'destination';
8
8
  name: string;
9
9
  allowedActions?: AllowedActions;
10
10
  }
@@ -17,16 +17,16 @@ export type AllowedActions = readonly string[];
17
17
  * counted as the server counts them.
18
18
  *
19
19
  * <p>`can(permission)` is about the whole installation. `can(permission, clusterId)` is about one cluster, and
20
- * `can(permission, { clusterId, kind, name })` about one queue or address, with a team's or share's rights counted.
20
+ * `can(permission, { clusterId, type, name })` about one subscription or destination, with a team's or share's rights counted.
21
21
  * Each is fetched the first time it is asked. Until it arrives the control is offered, as it is while grants load:
22
22
  * blocking on an answer not yet known would lock out someone the server lets in. For a resource permission the
23
- * cluster answer counts grants only; what a team or share gives on some queue or address is in the summary's
24
- * `anywhere`, and on one named queue or address in its own answer, or in the row's `allowedActions`.
23
+ * cluster answer counts grants only; what a team or share gives on some subscription or address is in the summary's
24
+ * `anywhere`, and on one named subscription or destination in its own answer, or in the row's `allowedActions`.
25
25
  *
26
- * <p>`canAnywhere` is the page-level right: held on the cluster by a grant, or on some queue or address through a team
26
+ * <p>`canAnywhere` is the page-level right: held on the cluster by a grant, or on some subscription or address through a team
27
27
  * or a share. A control is hidden only when it is false. `canOn` is the right on one row the server sent, from the
28
28
  * row's `allowedActions`: false there is a control shown disabled, with its reason. `createPatterns` are the name
29
- * patterns a team or share lets the caller create queues and addresses under.
29
+ * patterns a team or share lets the caller create subscriptions and destinations under.
30
30
  */
31
31
  export declare function useCan(): {
32
32
  can: (permission: string, where?: string | ResourceWhere) => boolean;
@@ -36,7 +36,7 @@ export declare function useCan(): {
36
36
  canOn: (permission: string, resource: {
37
37
  allowedActions: AllowedActions;
38
38
  }) => boolean;
39
- createPatterns: (clusterId: string, kind: "queue" | "address") => string[] | undefined;
39
+ createPatterns: (clusterId: string, type: "subscription" | "destination") => string[] | undefined;
40
40
  /** The teams the caller belongs to, with their role in each. */
41
41
  teams: {
42
42
  teamId: string;
@@ -5,9 +5,9 @@ import type { AnyRoute } from '@tanstack/react-router';
5
5
  import type { NavGroupId } from './nav/groups.ts';
6
6
  import type { SlotContributions } from './slots.ts';
7
7
  /** The extension contract version, shared with the backend's `Contract.VERSION` (ADR-0070). */
8
- export declare const CONTRACT = 15;
8
+ export declare const CONTRACT = 17;
9
9
  /** The module ids the backend manifest reports. A frontend feature uses the same id as its backend module. */
10
- export declare const FEATURE_IDS: readonly ["security", "audit", "auditfeed", "settings", "lifecycle", "stream", "inbox", "approvals", "broker", "clusters", "governance", "scrape", "mcp", "queues", "resources", "messages", "routing", "metrics", "alerting", "events", "rr", "sql", "brokerconfig", "flow", "triage", "bulk", "transfer", "setupreview", "diagnostics", "apitokens", "plugins", "identity-local", "identity-oidc"];
10
+ export declare const FEATURE_IDS: readonly ["security", "audit", "auditfeed", "settings", "lifecycle", "stream", "inbox", "approvals", "broker", "clusters", "governance", "scrape", "artemis", "mcp", "resources", "messages", "routing", "metrics", "alerting", "events", "rr", "sql", "brokerconfig", "flow", "triage", "bulk", "transfer", "setupreview", "diagnostics", "apitokens", "plugins", "identity-local", "identity-oidc"];
11
11
  export type FeatureId = (typeof FEATURE_IDS)[number];
12
12
  /**
13
13
  * An installed plugin's id, as its `plugin.json` declares it: lowercase kebab-case, vendor first,
@@ -36,6 +36,12 @@ export interface NavContribution {
36
36
  icon: Icon;
37
37
  /** The view's path below `/clusters/$clusterId/`. */
38
38
  path: string;
39
+ /**
40
+ * The id of the broker system the view is for (`artemis`). Without it the view applies to every system; with
41
+ * it, the navigation lists the view only for a cluster that runs that system, and its route is under
42
+ * `/clusters/$clusterId/<system>/`, which another system's cluster answers with the not-found page.
43
+ */
44
+ system?: string;
39
45
  /**
40
46
  * The permission the view reads with. Without it the entry stays visible and disabled,
41
47
  * and says why; the server enforces it regardless.
@@ -1,12 +1,13 @@
1
1
  import { type NavContribution } from '../feature.ts';
2
2
  /**
3
3
  * The views that have a `g` letter: built-in views only — a plugin's letter is ignored, so a plugin
4
- * can never take a letter an operator already relies on (ADR-0109).
4
+ * can never take a letter an operator already relies on (ADR-0109). A system-only view has no letter on a
5
+ * cluster known to run another system; while the system is not known the letter is offered.
5
6
  */
6
7
  export declare function viewHotkeys(features: {
7
8
  id: string;
8
9
  nav?: NavContribution[];
9
- }[]): Map<string, NavContribution>;
10
+ }[], systemId?: string): Map<string, NavContribution>;
10
11
  /**
11
12
  * The single-key shortcuts (ADR-0109), as one document listener mounted by the shell:
12
13
  * `g` then a view's letter goes to that view of the open cluster, `?` opens the list of shortcuts,
@@ -8,14 +8,15 @@ export interface CurrentView {
8
8
  }
9
9
  /**
10
10
  * Which cluster view an address is under (ADR-0109): the navigation entry whose path is the longest
11
- * prefix of the path after `/clusters/<id>/`, so a queue's message browser is under Queues and a
11
+ * prefix of the path after `/clusters/<id>/`, so a subscription's message browser is under Subscriptions and a
12
12
  * bulk run under Bulk runs. Null outside any cluster.
13
13
  */
14
14
  export declare function matchView(pathname: string, features: RahdarFeature[]): CurrentView | null;
15
15
  export declare function useCurrentView(): CurrentView | null;
16
16
  /**
17
17
  * The address of the same view on another cluster (ADR-0109): an operator comparing two clusters
18
- * stays on Queues. The view's search is not carried — its filter and its open resource name things
19
- * that may not exist there. Without a current view, the cluster's landing page.
18
+ * stays on Subscriptions. The view's search is not carried — its filter and its open resource name things
19
+ * that may not exist there. Without a current view, or when the view is for one system and the cluster runs
20
+ * another (`system`), the cluster's landing page.
20
21
  */
21
- export declare function sameViewOn(clusterId: string, view: CurrentView | null): string;
22
+ export declare function sameViewOn(clusterId: string, view: CurrentView | null, system?: string): string;
@@ -7,6 +7,7 @@ export interface NavGroup {
7
7
  }
8
8
  /**
9
9
  * The features' views under the kernel's groups (ADR-0070): groups in their fixed order, views in
10
- * their declared order, and a group none of the features contributes to left out.
10
+ * their declared order, and a group none of the features contributes to left out. A system-only view is
11
+ * listed only for a cluster that runs that system (`systemId`).
11
12
  */
12
- export declare function navGroups(features: RahdarFeature[]): NavGroup[];
13
+ export declare function navGroups(features: RahdarFeature[], systemId?: string): NavGroup[];
@@ -1,12 +1,15 @@
1
1
  import { type ComponentType, type ReactElement } from 'react';
2
2
  import type { ModuleId } from '../feature.ts';
3
+ import { type ResourceSearch } from './search.ts';
3
4
  /** The root every page renders inside: the shell. A feature's `routes.root` are its children. */
4
5
  export declare const rootRoute: import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
5
6
  /** One cluster's layout. A feature's `routes.cluster` are its children. */
6
7
  export declare const clusterRoute: import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "clusters/$clusterId", "/clusters/$clusterId", string, "/clusters/$clusterId", undefined, import("@tanstack/router-core").ResolveParams<"clusters/$clusterId">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
7
8
  export declare const pluginClusterFallback: import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "clusters/$clusterId", "/clusters/$clusterId", string, "/clusters/$clusterId", undefined, import("@tanstack/router-core").ResolveParams<"clusters/$clusterId">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "p/$pluginId/$", "/clusters/$clusterId/p/$pluginId/$", string, "/clusters/$clusterId/p/$pluginId/$", undefined, import("@tanstack/router-core").ResolveParams<"p/$pluginId/$">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
8
9
  /** The shell's own pages, beside the cluster layout. */
9
- export declare const shellRoutes: (import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/", "/", string, "/", undefined, import("@tanstack/router-core").ResolveParams<"/">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined> | import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "login", "/login", string, "/login", undefined, import("@tanstack/router-core").ResolveParams<"login">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined> | import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "admin", "/admin", string, "/admin", (raw: Record<string, unknown>) => {
10
+ export declare const shellRoutes: (import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/", "/", string, "/", (raw: Record<string, unknown>) => ResourceSearch & {
11
+ cluster?: string;
12
+ }, import("@tanstack/router-core").ResolveParams<"/">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined> | import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "login", "/login", string, "/login", undefined, import("@tanstack/router-core").ResolveParams<"login">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined> | import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "admin", "/admin", string, "/admin", (raw: Record<string, unknown>) => {
10
13
  tab?: string;
11
14
  plugin?: string;
12
15
  upload?: string;
@@ -0,0 +1,7 @@
1
+ /** A listing's navigable state: filter, sort and page live in the URL, not in local state (non-negotiable #9). */
2
+ export interface ResourceSearch {
3
+ q?: string;
4
+ sort?: string;
5
+ page?: number;
6
+ }
7
+ export declare function validateResourceSearch(raw: Record<string, unknown>): ResourceSearch;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ⌘K navigation across the console: jump to a view, a recent place, a cluster, or a queue by name, or
2
+ * ⌘K navigation across the console: jump to a view, a recent place, a cluster, or a subscription by name, or
3
3
  * search a live view (ADR-0109). Mounted once in the root layout; the shortcut is registered by
4
4
  * {@link Spotlight}, and the header's Search button opens it too.
5
5
  *
@@ -1,6 +1,2 @@
1
- /**
2
- * The landing page, with no cluster open: what the features contribute for it. The clusters feature
3
- * sends the operator to the first cluster, so the page is seen only while that is decided or while no
4
- * cluster is registered, which is what it is titled for.
5
- */
1
+ /** The landing page, with no cluster open: the estate, which is what the features contribute for it. */
6
2
  export declare function HomeView(): import("react").JSX.Element;
@@ -6,7 +6,7 @@
6
6
  export interface LastPlace {
7
7
  clusterId: string;
8
8
  clusterName: string;
9
- /** The view the operator was in, such as "Queues". */
9
+ /** The view the operator was in, such as "Subscriptions". */
10
10
  label: string;
11
11
  /** The address, and the search it was opened with. */
12
12
  to: string;
@@ -0,0 +1,11 @@
1
+ import type { components } from '../api/schema.d.ts';
2
+ type ClusterDetail = components['schemas']['ClusterDetail'];
3
+ /**
4
+ * What the cluster says about its broker system: the system itself and the kinds it offers, each with the verbs
5
+ * it supports. It reads the cluster the clusters feature already keeps fresh, under the same key, so it adds
6
+ * no request of its own. `undefined` until the cluster has loaded, and for no cluster.
7
+ */
8
+ export declare function useClusterKinds(clusterId: string | undefined): Pick<ClusterDetail, 'system' | 'kinds'> | undefined;
9
+ /** The id of the system the cluster runs (`artemis`), which decides whether a system-only view is offered. */
10
+ export declare function useClusterSystem(clusterId: string | undefined): string | undefined;
11
+ export {};
@@ -1,9 +1,9 @@
1
1
  import type { ComponentType } from 'react';
2
- import type { ActionProps, ActionSection, AddressTarget, ClientTarget, ConnectionTarget, ConsumerTarget, DivertTarget, LinkProps, MessageTarget, ProducerTarget, QueueTarget, SessionTarget } from './actions/types.ts';
2
+ import type { ActionProps, ActionSection, ChannelTarget, ClientTarget, ConnectionTarget, ConsumerTarget, DestinationTarget, LinkProps, MessageTarget, ProducerTarget, ResourceRef, RouteTarget, SubscriptionTarget } from './actions/types.ts';
3
3
  import type { HeldOperationDetail } from './approvals/api.ts';
4
4
  import type { MetricRange } from './time/ranges.ts';
5
- /** Queues picked by name, or every queue matching the queues screen's filter (`q`, blank for all). */
6
- export type QueueSelection = {
5
+ /** Subscriptions picked by name, or every subscription matching the subscriptions screen's filter (`q`, blank for all). */
6
+ export type SubscriptionSelection = {
7
7
  kind: 'names';
8
8
  names: string[];
9
9
  } | {
@@ -11,7 +11,7 @@ export type QueueSelection = {
11
11
  q: string;
12
12
  total: number;
13
13
  };
14
- /** Messages picked by id, every message matching the messages screen's selector, or the whole queue. */
14
+ /** Messages picked by id, every message matching the messages screen's selector, or the whole subscription. */
15
15
  export type MessageSelection = {
16
16
  kind: 'ids';
17
17
  ids: number[];
@@ -34,7 +34,7 @@ export interface SlotProps {
34
34
  collapsed: boolean;
35
35
  };
36
36
  /** The landing page, when no cluster is open. */
37
- 'home.empty': object;
37
+ 'home.estate': object;
38
38
  /** Above every view of a cluster: what identifies it, and what needs saying about its state. */
39
39
  'cluster.header': {
40
40
  clusterId: string;
@@ -43,20 +43,20 @@ export interface SlotProps {
43
43
  'cluster.registration.afterProbe': {
44
44
  contributions: Record<string, unknown>;
45
45
  };
46
- /** In a queue's detail drawer, below its per-node breakdown. `onClose` closes the drawer before navigating. */
47
- 'queue.detail.panels': {
46
+ /** In a subscription's detail drawer, below its per-node breakdown. `onClose` closes the drawer before navigating. */
47
+ 'subscription.detail.panels': {
48
48
  clusterId: string;
49
- queueName: string;
49
+ subscription: ResourceRef;
50
50
  onClose: () => void;
51
51
  };
52
52
  /**
53
- * Beside the queues screen's selection: what can be done to the selected queues. `count` is how
53
+ * Beside the subscriptions screen's selection: what can be done to the selected subscriptions. `count` is how
54
54
  * many are selected, and may be zero: an action then stays visible and disabled. `clear` empties
55
55
  * the selection.
56
56
  */
57
- 'queues.selection': {
57
+ 'subscriptions.selection': {
58
58
  clusterId: string;
59
- selection: QueueSelection;
59
+ selection: SubscriptionSelection;
60
60
  count: number;
61
61
  clear: () => void;
62
62
  };
@@ -67,7 +67,7 @@ export interface SlotProps {
67
67
  */
68
68
  'messages.selection': {
69
69
  clusterId: string;
70
- queueName: string;
70
+ subscription: ResourceRef;
71
71
  node?: string;
72
72
  selection: MessageSelection;
73
73
  total: number | null;
@@ -77,10 +77,10 @@ export interface SlotProps {
77
77
  'metrics.panels': {
78
78
  clusterId: string;
79
79
  };
80
- /** In the flow view's monitoring pane, when a queue is selected: its history over `range`, per node. */
80
+ /** In the flow view's monitoring pane, when a subscription is selected: its history over `range`, per node. */
81
81
  'flow.selection.panels': {
82
82
  clusterId: string;
83
- queueName: string;
83
+ subscription: ResourceRef;
84
84
  range: MetricRange;
85
85
  };
86
86
  /** Inside a box on the topology graph, after its name. `nodeIds` are the broker endpoints the box stands for. */
@@ -92,8 +92,8 @@ export interface SlotProps {
92
92
  'settings.sections': {
93
93
  clusterId: string;
94
94
  };
95
- /** A tab of a cluster's Routing page, after Diverts and Bridges, labelled with the contribution's title; its id is the tab's `?tab=`. */
96
- 'routing.tabs': {
95
+ /** A tab of a cluster's Routes page, after Routes, labelled with the contribution's title; its id is the tab's `?tab=`. */
96
+ 'routes.tabs': {
97
97
  clusterId: string;
98
98
  };
99
99
  /**
@@ -120,19 +120,19 @@ export interface SlotProps {
120
120
  opened: boolean;
121
121
  onClose: () => void;
122
122
  };
123
- 'queue.actions': ActionProps<QueueTarget>;
124
- 'address.actions': ActionProps<AddressTarget>;
123
+ 'subscription.actions': ActionProps<SubscriptionTarget>;
124
+ 'destination.actions': ActionProps<DestinationTarget>;
125
125
  'connection.actions': ActionProps<ConnectionTarget>;
126
- 'session.actions': ActionProps<SessionTarget>;
126
+ 'channel.actions': ActionProps<ChannelTarget>;
127
127
  'consumer.actions': ActionProps<ConsumerTarget>;
128
128
  'producer.actions': ActionProps<ProducerTarget>;
129
129
  'message.actions': ActionProps<MessageTarget>;
130
- 'divert.actions': ActionProps<DivertTarget>;
130
+ 'route.actions': ActionProps<RouteTarget>;
131
131
  'client.actions': ActionProps<ClientTarget>;
132
- 'queue.link': LinkProps<QueueTarget>;
133
- 'address.link': LinkProps<AddressTarget>;
132
+ 'subscription.link': LinkProps<SubscriptionTarget>;
133
+ 'destination.link': LinkProps<DestinationTarget>;
134
134
  'connection.link': LinkProps<ConnectionTarget>;
135
- 'session.link': LinkProps<SessionTarget>;
135
+ 'channel.link': LinkProps<ChannelTarget>;
136
136
  }
137
137
  export type SlotName = keyof SlotProps;
138
138
  /**
@@ -186,6 +186,11 @@ export interface SlotContribution<P> {
186
186
  * (listed under Plugins without one), and an `AdminGroupId`, required, for `admin.tabs`.
187
187
  */
188
188
  group?: string;
189
+ /**
190
+ * `routes.tabs` only: the id of the broker system the tab is for (`artemis`). The tab is listed only on a
191
+ * cluster that runs that system.
192
+ */
193
+ system?: string;
189
194
  /** `*.actions` only: the menu section the item is listed under. */
190
195
  section?: ActionSection;
191
196
  Component: ComponentType<P>;
@@ -19,7 +19,7 @@ import { StatusBadge } from '../ui/StatusBadge.tsx';
19
19
  import { Toolbar } from '../ui/Toolbar.tsx';
20
20
  export { CONTRACT } from '../kernel/feature.ts';
21
21
  export type { NavContribution, PaletteSource, PluginId, RouteContributions, RahdarFeature, TopicHandler, } from '../kernel/feature.ts';
22
- export { ADMIN_GROUPS, SETTINGS_GROUPS, type AdminGroupId, type MessageSelection, type QueueSelection, type SettingsGroupId, type SlotContribution, type SlotContributions, type SlotEntry, type SlotName, type SlotProps, } from '../kernel/slots.ts';
22
+ export { ADMIN_GROUPS, SETTINGS_GROUPS, type AdminGroupId, type MessageSelection, type SubscriptionSelection, type SettingsGroupId, type SlotContribution, type SlotContributions, type SlotEntry, type SlotName, type SlotProps, } from '../kernel/slots.ts';
23
23
  export { NAV_GROUPS, type NavGroupId } from '../kernel/nav/groups.ts';
24
24
  export { clusterRoute, rootRoute } from '../kernel/routing/roots.ts';
25
25
  export { ApiError, clusterKey, heldOperationsKey, OperationHeldError, request, type HeldOperation, } from '../kernel/api/request.ts';
@@ -37,7 +37,7 @@ export { StepUpPrompt } from '../kernel/auth/StepUp.tsx';
37
37
  */
38
38
  export { useUserStream } from '../kernel/stream/useUserStream.ts';
39
39
  export type { StreamStatus } from '../kernel/stream/useClusterStream.ts';
40
- export { ACTION_SECTIONS, type ActionHost, type ActionMode, type ActionProps, type ActionSection, type ActionTargets, type AddressTarget, type ClientTarget, type ConnectionTarget, type ConsumerTarget, type DivertTarget, type HostedDialogProps, type MessageTarget, type ProducerTarget, type QueueTarget, type SessionTarget, } from '../kernel/actions/types.ts';
40
+ export { ACTION_SECTIONS, type ActionHost, type ActionMode, type ActionProps, type ActionSection, type ActionTargets, type ChannelTarget, type ClientTarget, type ConnectionTarget, type ConsumerTarget, type DestinationTarget, type HostedDialogProps, type MessageTarget, type ProducerTarget, type ResourceRef, type RouteTarget, type SubscriptionTarget, } from '../kernel/actions/types.ts';
41
41
  export { ActionMenuItem } from '../ui/ActionMenuItem.tsx';
42
42
  export { CapabilityGate } from '../ui/CapabilityGate.tsx';
43
43
  export { gateFor, type GateScope, type GateVerdict } from '../ui/capabilityGate.ts';
@@ -6,7 +6,7 @@ import { type ReactNode } from 'react';
6
6
  * <ul>
7
7
  * <li>With `tone="danger"` the action is confirmed by pressing and holding the button until it
8
8
  * fills ({@link HoldToConfirm}), never by a click or by typing; use it for anything that removes
9
- * or overwrites. The button names the action and its count, such as "Delete 37 queues".
9
+ * or overwrites. The button names the action and its count, such as "Delete 37 subscriptions".
10
10
  * <li>Focus enters the dialog on Cancel, Escape closes it, and focus returns to the control that
11
11
  * opened it.
12
12
  * <li>While `pending` the button is busy and cannot be pressed again, and the dialog stays
@@ -22,11 +22,11 @@ export declare function ConfirmDialog({ opened, onClose, title, consequence, con
22
22
  export type ConfirmDialogProps = Readonly<{
23
23
  opened: boolean;
24
24
  onClose: () => void;
25
- /** The action as a plain line, such as "Delete queue". */
25
+ /** The action as a plain line, such as "Delete subscription". */
26
26
  title: string;
27
27
  /** What it affects: the resource, the nodes and how much data goes. */
28
28
  consequence: ReactNode;
29
- /** The exact action, such as "Delete queue". */
29
+ /** The exact action, such as "Delete subscription". */
30
30
  confirmLabel: string;
31
31
  /**
32
32
  * The button that dismisses without acting; defaults to "Cancel". Name what is kept, such as "Keep
@@ -12,7 +12,7 @@ export type DescriptionItem = Readonly<{
12
12
  * two term and value pairs side by side for a short list in a wide space. A `label` names the list
13
13
  * for assistive technology.
14
14
  *
15
- * `oneLine` is for terms and values that are names a broker supplies (a queue, an address, a role), in
15
+ * `oneLine` is for terms and values that are names a broker supplies (a subscription, an address, a role), in
16
16
  * a cell with a width of its own: each stays on one line, shortened in the middle when it does not fit
17
17
  * and named in full on hover and focus, and neither track shrinks below a readable width, so a long
18
18
  * name never squeezes its neighbour into a column of characters. A value that is not a string shortens
@@ -17,7 +17,7 @@ import { type ReactNode } from 'react';
17
17
  export declare function EmptyState(props: EmptyStateProps): import("react").JSX.Element;
18
18
  export type EmptyStateProps = Readonly<{
19
19
  kind: 'empty';
20
- /** What is missing, such as "No queues". */
20
+ /** What is missing, such as "No subscriptions". */
21
21
  title: string;
22
22
  /** What the resource is and why there is none. */
23
23
  description: ReactNode;
@@ -5,12 +5,12 @@
5
5
  * finger or a pen, or with Space or Enter on the keyboard; the hint under the button says so, and the
6
6
  * outcome is announced.
7
7
  *
8
- * <p>`label` is the action ("Delete 37 queues") and names the blast radius the button is for; the button
8
+ * <p>`label` is the action ("Delete 37 subscriptions") and names the blast radius the button is for; the button
9
9
  * reads exactly that, and the hint under it says to hold it. While `loading` it is busy and cannot be held again. Mouse and touch
10
10
  * presses are Mantine's `useLongPress`; it has no keyboard, which is handled here.
11
11
  */
12
12
  export declare function HoldToConfirm({ label, onConfirm, loading, disabled, describedBy, tone, }: Readonly<{
13
- /** The exact action, such as "Delete queue ORDERS" or "Apply to 2 nodes". */
13
+ /** The exact action, such as "Delete subscription ORDERS" or "Apply to 2 nodes". */
14
14
  label: string;
15
15
  onConfirm: () => void;
16
16
  loading?: boolean;
@@ -5,7 +5,7 @@
5
5
  * `loading` props, which hold their own size.
6
6
  */
7
7
  export declare function LoadingState({ label, variant, blockSize, inlineSize, }: Readonly<{
8
- /** What is loading, such as "Loading queues". Read aloud, not shown. */
8
+ /** What is loading, such as "Loading subscriptions". Read aloud, not shown. */
9
9
  label: string;
10
10
  /** `block` fills the width it is in; `inline` sits in a line of text. */
11
11
  variant?: 'block' | 'inline';
@@ -23,7 +23,7 @@ export declare function NodeOutcomeSummary({ outcome, destructive, alreadyLabel,
23
23
  */
24
24
  alreadyLabel?: string;
25
25
  /**
26
- * What the counts are counting, and the verb for them. Defaults to the queue
26
+ * What the counts are counting, and the verb for them. Defaults to the subscription
27
27
  * delete's wording; a connection close affects consumers, not messages, and
28
28
  * saying "destroyed" there would overstate what happened.
29
29
  */
@@ -8,7 +8,7 @@ import { type ReactNode } from 'react';
8
8
  * controls that belong together; a toolbar of one or two is better as plain tab stops.
9
9
  */
10
10
  export declare function Toolbar({ label, start, end, arrowNavigation, }: Readonly<{
11
- /** Names the toolbar for assistive technology, such as "Queue filters". */
11
+ /** Names the toolbar for assistive technology, such as "Subscription filters". */
12
12
  label: string;
13
13
  /** Controls that act on the view, on the start side. */
14
14
  start?: ReactNode;
@@ -10,25 +10,26 @@ export type GateVerdict = {
10
10
  };
11
11
  /** What a permission is held on: one cluster, or Rahdar itself. */
12
12
  export type GateScope = 'cluster' | 'installation';
13
- /** What is known of a refusal on one queue or address: the permission, and who owns it, to say who can grant it. */
13
+ /** What is known of a refusal on one subscription or destination: the permission, and who owns it, to say who can grant it. */
14
14
  export interface ResourceDenial {
15
15
  permission: string;
16
- noun: 'queue' | 'address';
16
+ noun: 'subscription' | 'destination';
17
17
  /** The name of the team that owns the resource; none when no team does. */
18
18
  owner?: string | null;
19
19
  }
20
20
  /**
21
21
  * Whether a lifecycle control may act, and why not when it may not.
22
22
  *
23
- * <p>Two independent gates, in the order the operator can do something about:
23
+ * <p>Two independent gates, checked in this order (a kind that lacks the verb comes before both, in
24
+ * `useKindVerbRefusal`):
24
25
  *
25
26
  * <ul>
26
- * <li><b>Permission</b> — the caller's own grants. The server is the
27
- * enforcement point; this only explains, and never hides.
28
27
  * <li><b>Capability</b> — whether the broker connection can write at all. Only
29
28
  * a known refusal blocks. Since ADR-0049 D5 an unproven capability is
30
29
  * reported as unknown, and blocking on the absence of evidence would stop
31
30
  * an operator using a broker that works perfectly well.
31
+ * <li><b>Permission</b> — the caller's own grants. The server is the
32
+ * enforcement point; this only explains, and never hides.
32
33
  * </ul>
33
34
  *
34
35
  * <p>`scope` is what the permission is held on, so the reason names the right place: `cluster` for
@@ -38,6 +39,6 @@ export interface ResourceDenial {
38
39
  export declare function gateFor(permitted: boolean, permissionLabel: string, capability: CapabilityView | undefined,
39
40
  /** True while the caller's grants are still being fetched. */
40
41
  loading?: boolean, scope?: GateScope,
41
- /** Given for a control on one queue or address the caller can see: the reason then names the permission and whom to ask. */
42
+ /** Given for a control on one subscription or destination the caller can see: the reason then names the permission and whom to ask. */
42
43
  denial?: ResourceDenial): GateVerdict;
43
44
  export {};
@@ -14,7 +14,7 @@ export type ActionVerb = Readonly<{
14
14
  }>;
15
15
  type Notice = Readonly<{
16
16
  action: ActionVerb;
17
- /** What the action acts on, such as `queue "orders"`. */
17
+ /** What the action acts on, such as `subscription "orders"`. */
18
18
  subject: string;
19
19
  }>;
20
20
  /** Settles a toast that {@link notify.pending} returned: it is replaced by the outcome. */
@@ -12,7 +12,7 @@ interface DataTableBaseProps<T> {
12
12
  columns: Column<T>[];
13
13
  data: T[];
14
14
  rowKey: (row: T) => string;
15
- /** What the table lists, as its accessible name: "Queues", "Connections". */
15
+ /** What the table lists, as its accessible name: "Subscriptions", "Connections". */
16
16
  label: string;
17
17
  /** Shown in place of the rows when there are none: an `EmptyState`. */
18
18
  empty: ReactNode;
@@ -46,4 +46,13 @@ interface KindPreset {
46
46
  mono: boolean;
47
47
  }
48
48
  export declare const KIND_PRESETS: Record<ColumnKind, KindPreset>;
49
+ /**
50
+ * The Kind column of a list of one role: what the row's system calls its kind ("Queue", "Divert"). It is
51
+ * `low` so a narrow table drops it first; the name still identifies the row.
52
+ */
53
+ export declare function kindColumn<T extends {
54
+ kindLabel: string;
55
+ }>(): Column<T>;
56
+ /** The same column for rows that hold the label deeper, such as a dead-letter row's subscription. */
57
+ export declare function kindColumn<T>(label: (row: T) => string): Column<T>;
49
58
  export {};
@@ -1,5 +1,5 @@
1
1
  export { DataTable, STATIC_ROW_LIMIT, type DataTableProps, type TableToolbar } from './DataTable.tsx';
2
- export { KIND_PRESETS, type Column, type ColumnKind, type ColumnPriority } from './columns.ts';
2
+ export { KIND_PRESETS, kindColumn, type Column, type ColumnKind, type ColumnPriority } from './columns.ts';
3
3
  export { DENSITY_KEY, densityToggleLabel, useDensity, type Density } from './density.ts';
4
4
  export type { RowMenu, RowMenuContext } from './GridTable.tsx';
5
5
  export { MiddleTruncate } from './MiddleTruncate.tsx';