mqgov-cli 0.2.0 → 0.3.0

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 (2) hide show
  1. package/README.md +53 -9
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Governed message-broker operations for humans _and_ AI agents.**
6
6
 
7
- One safe command line for **Kafka**, **RabbitMQ**, **Pulsar**, and **RocketMQ** — list, describe, peek, tail, produce, reset offsets, inspect ACLs, purge, and delete topics without ever fat-fingering production or silently draining a queue.
7
+ One safe command line for **Kafka**, **RabbitMQ**, **Pulsar**, and **RocketMQ** — list, describe, peek, tail, produce, govern DLQs, reset offsets, inspect ACLs and schemas, purge, and delete topics without ever fat-fingering production or silently draining a queue.
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/mqgov-cli.svg)](https://www.npmjs.com/package/mqgov-cli)
10
10
  [![CI](https://github.com/JiangHe12/mqgov-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/JiangHe12/mqgov-cli/actions/workflows/ci.yml)
@@ -38,7 +38,7 @@ It's built on the shared [`opskit-core`](https://github.com/JiangHe12/opskit-cor
38
38
  | | |
39
39
  |---|---|
40
40
  | 📨 **Four brokers** | **Kafka** (franz-go), **RabbitMQ** (AMQP + management API), **Pulsar** (client + admin REST), **RocketMQ** (rocketmq-client-go/v2). One backend-agnostic governance model; pick per context or override per command. |
41
- | 🧱 **topic / group / message / acl** | topics: list · describe · create · alter · delete · purge. consumer groups: list · lag · reset-offset. messages: non-destructive peek · tail · produce. ACLs: list · grant · revoke where supported. |
41
+ | 🧱 **topic / group / message / dlq / acl / schema / fleet** | topics: list · describe · create · alter · delete · purge. consumer groups: list · lag · reset-offset. messages: non-destructive peek · tail · produce. DLQs: list · peek · redrive · purge through native broker models. ACLs: list · grant · revoke where supported. Schemas: list · describe · check where native schema registry support exists. Fleet: read-only status and topic inventory across configured contexts. |
42
42
  | 🔐 **R0–R3 governance** | every operation is risk-classified by the fail-closed `mqclass` engine; protected contexts and internal/system topics escalate one tier; AI callers can never self-authorize. |
43
43
  | 🎯 **Real blast-radius preview** | `reset-offset --dry-run` and `purge --dry-run` compute the actual per-partition message delta from the live broker — no guessing. The preview is read-only and never mutates. |
44
44
  | 👀 **Non-destructive peek/tail** | inspect or stream messages as fingerprints without consuming them or moving any cursor (Kafka direct partition reads, Pulsar Reader, RabbitMQ get+requeue for peek only). Where a broker can't guarantee this, the operation fails closed rather than silently consuming. |
@@ -58,10 +58,14 @@ It's built on the shared [`opskit-core`](https://github.com/JiangHe12/opskit-cor
58
58
  | **offset lag / reset** | ✅ | ✅ (cursor) | ❌ (no offsets) | ❌ |
59
59
  | alter partitions | ✅ | ✅ | ❌ | ❌ |
60
60
  | purge | ✅ | ✅ | ✅ | ❌ |
61
- | **ACL list / grant / revoke** | ✅ | ✅ namespace/topic permissions | ✅ user-vhost permissions | ❌ `NOT_IMPLEMENTED` |
61
+ | **DLQ list / peek / redrive / purge** | list ❌; explicit topic peek/redrive/purge ✅ | ✅ `{topic}-{subscription}-DLQ` | ✅ DLX queues | list ✅ `%DLQ%group`; others ❌ |
62
+ | **ACL list / grant / revoke** | ✅ | ✅ namespace/topic permissions | ✅ user-vhost permissions | ❌ `NOT_IMPLEMENTED`³ |
63
+ | **schema list / describe / check** | ✅ Confluent Schema Registry | ✅ built-in admin schema API | ❌ `NOT_IMPLEMENTED` | ❌ `NOT_IMPLEMENTED` |
62
64
 
63
65
  ¹ RocketMQ's Go v2 `PullConsumer` enters the consumer-group lifecycle and commits offsets, so it cannot guarantee non-destructive peek/tail — mqgov fails closed instead of silently advancing offsets. ² RabbitMQ has no forward non-destructive tail because reads are consume/requeue oriented. Unsupported operations always return `NOT_IMPLEMENTED` (exit 12), never a fake success.
64
66
 
67
+ ³ RocketMQ broker ACLs live in broker-side `plain_acl.yml`, but `rocketmq-client-go/v2` does not expose a public, cgo-free admin API for reading or changing that config. mqgov does not shell out to the Java `mqadmin` tool and does not hand-roll remoting commands; manage RocketMQ ACLs out of band with broker configuration or official mqadmin until the Go client exposes a clean API.
68
+
65
69
  ---
66
70
 
67
71
  ## 📦 Install
@@ -124,10 +128,10 @@ Every command is sorted into one of four **risk tiers** by the fail-closed `mqcl
124
128
 
125
129
  | Tier | What it covers | What you must provide |
126
130
  |:---:|---|---|
127
- | **R0** | Reads & previews (`topic list/describe`, `group list/lag`, `message peek`, `message tail`, `acl list`, `*-dry-run`, `audit query/verify`, `doctor`) | Nothing — but it's still audited |
131
+ | **R0** | Reads & previews (`topic list/describe`, `group list/lag`, `message peek`, `message tail`, `dlq list/peek`, `acl list`, `schema list/describe/check`, `fleet status/topics`, `*-dry-run`, `audit query/verify`, `doctor`) | Nothing — but it's still audited |
128
132
  | **R1** | Ordinary writes (`message produce`, `topic create`) | `--yes` (or an interactive confirmation) |
129
133
  | **R2** | Elevated mutations (`topic alter`, `group create/delete`, `acl grant`, produce to a **protected** topic) | `--yes` **and** a non-empty `--ticket` |
130
- | **R3** | Destructive / irreversible (`group reset-offset`, `topic purge`, `topic delete`, broad `acl grant`, `acl revoke`, produce to an **internal/system** topic) | The above **plus** the exact `--allow-*` flag |
134
+ | **R3** | Destructive / irreversible (`group reset-offset`, `topic purge`, `topic delete`, `dlq redrive`, `dlq purge`, broad `acl grant`, `acl revoke`, produce to an **internal/system** topic) | The above **plus** the exact `--allow-*` flag |
131
135
 
132
136
  The R3 allow flags: `--allow-offset-reset`, `--allow-topic-purge`, `--allow-topic-delete`, `--allow-destructive-acl`, `--allow-internal-produce`.
133
137
 
@@ -193,6 +197,46 @@ mqgov message produce <topic> [--key <k>] [--body <text>] --yes
193
197
  `peek` and `tail` never consume a message or move a cursor, and return only sha256 fingerprints (`keySha256`, `bodySha256`, size, optional timestamp) — never the body. `tail` is bounded by `--max-messages` and `--timeout`; `--follow` streams new messages only until those bounds or cancellation. Tail is supported by Kafka and Pulsar. On RabbitMQ and RocketMQ, `tail` fails closed (`NOT_IMPLEMENTED`); on RocketMQ, `peek` also fails closed.
194
198
  </details>
195
199
 
200
+ <details>
201
+ <summary><b>dlq</b> — dead-letter queue governance</summary>
202
+
203
+ ```bash
204
+ mqgov dlq list [--topic <source-or-dlq>] [--group <group-or-sub>] [--pattern <name|glob>] -o json # R0
205
+ mqgov dlq peek <dlq> [--topic <source>] [--group <group-or-sub>] [--count N] -o json # R0, fingerprints only
206
+ mqgov dlq redrive <dlq> --target <live-topic> [--count N] --dry-run -o json # R0 preview
207
+ mqgov dlq redrive <dlq> --target <live-topic> [--count N] --yes --ticket <t> --allow-internal-produce # R3
208
+ mqgov dlq purge <dlq> --dry-run -o json # R0 preview
209
+ mqgov dlq purge <dlq> --yes --ticket <t> --allow-topic-purge # R3
210
+ ```
211
+
212
+ DLQ mapping is backend-native and honest: RocketMQ lists `%DLQ%{consumerGroup}` topics only; RabbitMQ treats DLQs as ordinary queues fed by a dead-letter exchange; Kafka has no native DLQ and never auto-discovers one, so use an explicit DLQ topic for peek/redrive/purge; Pulsar uses `{topic}-{subscription}-DLQ`. Unsupported verbs return `NOT_IMPLEMENTED`.
213
+
214
+ Redrive is governed as internal produce: dry-run is a read-only preview and real execution requires `--allow-internal-produce`. Audit remains fingerprint/count-only and never stores message body, key, or headers.
215
+ </details>
216
+
217
+ <details>
218
+ <summary><b>schema</b> — schema registry</summary>
219
+
220
+ ```bash
221
+ mqgov schema list [--pattern <subject>] -o json
222
+ mqgov schema describe <subject-or-topic> [--version latest|N] -o json
223
+ mqgov schema check <subject-or-topic> --schema-file ./next.avsc --schema-type AVRO [--version latest] -o json
224
+ ```
225
+
226
+ `schema list`, `schema describe`, and `schema check` are R0 and audited. `check` uses read-only compatibility endpoints and never registers, deletes, or evolves a schema. Kafka maps to Confluent Schema Registry (`GET /subjects`, `GET /subjects/{subject}/versions`, `GET /subjects/{subject}/versions/{version|latest}`, and `POST /compatibility/subjects/{subject}/versions/{version}`). Pulsar maps to its built-in admin schema endpoints under `/admin/v2/schemas/{tenant}/{namespace}/{topic}`. RabbitMQ and RocketMQ fail closed with `NOT_IMPLEMENTED`. Audit stores only subject/version metadata and schema hashes, never schema text or registry credentials.
227
+ </details>
228
+
229
+ <details>
230
+ <summary><b>fleet</b> — cross-context read-only views</summary>
231
+
232
+ ```bash
233
+ mqgov fleet status --all -o json
234
+ mqgov fleet topics --contexts dev,staging --pattern orders -o json
235
+ ```
236
+
237
+ `fleet status` fans out `Ping`, `Describe`, and `Capabilities` across selected contexts. `fleet topics` fans out topic listing and tags every row with its source context. Select contexts with exactly one of `--all` or `--contexts a,b,c`. Fleet is R0 only: each per-context read still runs through the same R0 classification and authorization path as a single-context command, using that context's own stored credentials. Partial failures are reported per context as `denied`, `unreachable`, or `error` data and the command still exits 0.
238
+ </details>
239
+
196
240
  <details>
197
241
  <summary><b>acl</b> — broker access control</summary>
198
242
 
@@ -224,7 +268,7 @@ mqgov acl revoke --principal app-role --resource-type topic --resource-name orde
224
268
  --yes --ticket <t> --allow-destructive-acl
225
269
  ```
226
270
 
227
- `acl list` is R0 and audited. Normal `acl grant` is R2. Broad grants (Kafka prefixed pattern, wildcard principal, wildcard resource, cluster resource, `all`, `alter`, cluster-action style operations, broad RabbitMQ regexes such as `.*`, `.+`, `.`, and `orders.*`, or Pulsar `functions`/`sources`/`sinks`/`packages`) and every `acl revoke` are R3 and require `--allow-destructive-acl`. Kafka implements broker ACLs with `literal`/`prefixed` patterns. RabbitMQ maps ACLs to native per-user, per-vhost permission regexes (`configure`, `write`, `read`) and only supports `--permission allow` with `--pattern regex`. Pulsar maps ACLs to native role permissions on namespaces or topics with actions `produce`, `consume`, `functions`, `sources`, `sinks`, and `packages`; it is allow-only and uses `--pattern literal`. RocketMQ fails closed with `NOT_IMPLEMENTED`.
271
+ `acl list` is R0 and audited. Normal `acl grant` is R2. Broad grants (Kafka prefixed pattern, wildcard principal, wildcard resource, cluster resource, `all`, `alter`, cluster-action style operations, broad RabbitMQ regexes such as `.*`, `.+`, `.`, and `orders.*`, or Pulsar `functions`/`sources`/`sinks`/`packages`) and every `acl revoke` are R3 and require `--allow-destructive-acl`. Kafka implements broker ACLs with `literal`/`prefixed` patterns. RabbitMQ maps ACLs to native per-user, per-vhost permission regexes (`configure`, `write`, `read`) and only supports `--permission allow` with `--pattern regex`. Pulsar maps ACLs to native role permissions on namespaces or topics with actions `produce`, `consume`, `functions`, `sources`, `sinks`, and `packages`; it is allow-only and uses `--pattern literal`. RocketMQ fails closed with `NOT_IMPLEMENTED`: broker ACLs are managed through broker-side `plain_acl.yml` or the official Java `mqadmin`, because `rocketmq-client-go/v2` exposes no clean public ACL admin API.
228
272
  </details>
229
273
 
230
274
  <details>
@@ -232,12 +276,12 @@ mqgov acl revoke --principal app-role --resource-type topic --resource-name orde
232
276
 
233
277
  ```bash
234
278
  # Backend-bound contexts (credentials go through credstore, never plaintext)
235
- mqgov ctx set <name> --backend kafka --brokers <h:p,h:p> [--sasl-mechanism PLAIN] [--tls --ca-cert <f>] [--protected]
279
+ mqgov ctx set <name> --backend kafka --brokers <h:p,h:p> [--sasl-mechanism PLAIN] [--tls --ca-cert <f>] [--schema-registry-url <url>] [--schema-registry-username <u>] [--schema-registry-password <p>] [--protected]
236
280
  mqgov ctx set <name> --backend rabbitmq (--amqp-url <url> | --host <h> --port <p> --vhost </>) --management-url <url>
237
281
  mqgov ctx set <name> --backend pulsar --service-url pulsar://<h:p> --admin-url http://<h:p> [--tenant public] [--pulsar-namespace default]
238
282
  mqgov ctx set <name> --backend rocketmq --nameservers <h:p,h:p> [--broker-addr <h:p>]
239
283
  mqgov ctx use|list|current|delete|test
240
- # secrets: --password <pw|token|secretKey> --credential-backend <encrypted-file|keychain|...> (a non-plain backend is required)
284
+ # secrets: --password <pw|token|secretKey> and --schema-registry-password <pw> go through --credential-backend <encrypted-file|keychain|...> (a non-plain backend is required)
241
285
 
242
286
  # Audit (tamper-evident, fingerprint-only)
243
287
  mqgov audit query [--since 24h] [--type <t>] [--operator <o>] [--status <s>] [--limit 100] -o json
@@ -258,7 +302,7 @@ mqgov version
258
302
 
259
303
  mqgov-cli is designed to be driven by autonomous agents safely:
260
304
 
261
- - Run `mqgov capabilities -o json` first to discover what the bound backend supports — brokers differ, don't assume (e.g. Kafka, RabbitMQ, and Pulsar support `acl` with different native models; RabbitMQ/RocketMQ have no offsets; RabbitMQ/RocketMQ have no tail; RocketMQ has no peek).
305
+ - Run `mqgov capabilities -o json` first to discover what the bound backend supports — brokers differ, don't assume (e.g. Kafka, RabbitMQ, and Pulsar support `acl` with different native models; Kafka and Pulsar support `schema`; RabbitMQ/RocketMQ have no offsets, schema registry, or tail; RocketMQ has no peek). Use `fleet status --all -o json` for a read-only cross-context dashboard.
262
306
  - Use `-o json` everywhere; every command returns a stable, versioned envelope.
263
307
  - Get blast radius from `--dry-run` / `--plan`, never from your own reasoning.
264
308
  - **Never self-fill `--ticket`, `--allow-*`, or a high-risk `--yes`.** Surface the required human approval and stop.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mqgov-cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Governed message-broker operations CLI for AI agents (Kafka, RabbitMQ, Pulsar, RocketMQ)",
5
5
  "bin": {
6
6
  "mqgov": "bin/mqgov-cli.js",