@freelensapp/kafka-extension 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2025-2026 Freelens Authors.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
package/README.md ADDED
@@ -0,0 +1,432 @@
1
+ # @freelensapp/kafka-extension
2
+
3
+ <!-- markdownlint-disable MD013 -->
4
+
5
+ [![Home](https://img.shields.io/badge/%F0%9F%8F%A0-freelens.app-02a7a0)](https://freelens.app)
6
+ [![GitHub](https://img.shields.io/github/stars/freelensapp/freelens-kafka-extension?style=flat&label=GitHub%20%E2%AD%90)](https://github.com/freelensapp/freelens-kafka-extension)
7
+ [![DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/freelensapp/freelens-kafka-extension)
8
+ [![Release](https://img.shields.io/github/v/release/freelensapp/freelens-kafka-extension?display_name=tag&sort=semver)](https://github.com/freelensapp/freelens-kafka-extension/releases)
9
+ [![Unit tests](https://github.com/freelensapp/freelens-kafka-extension/actions/workflows/unit-tests.yaml/badge.svg?branch=main)](https://github.com/freelensapp/freelens-kafka-extension/actions/workflows/unit-tests.yaml)
10
+ [![Integration tests](https://github.com/freelensapp/freelens-kafka-extension/actions/workflows/integration-tests.yaml/badge.svg?branch=main)](https://github.com/freelensapp/freelens-kafka-extension/actions/workflows/integration-tests.yaml)
11
+ [![npm](https://img.shields.io/npm/v/@freelensapp/kafka-extension.svg)](https://www.npmjs.com/package/@freelensapp/kafka-extension)
12
+
13
+ <!-- markdownlint-enable MD013 -->
14
+
15
+ ## Overview
16
+
17
+ [Freelens](https://freelens.app) extension for **Apache Kafka**: discover the
18
+ Kafka clusters running in, or used by, your Kubernetes cluster and inspect
19
+ them without leaving Freelens and without manual `kubectl port-forward`
20
+ gymnastics.
21
+
22
+ The extension is a cluster-native Kafka console. It lives inside a Freelens
23
+ session that is already authenticated to a Kubernetes cluster, so it can
24
+ auto-discover Kafka endpoints (Strimzi `Kafka` resources, Services exposing
25
+ Kafka ports, and external or managed Kafka such as Amazon MSK, Confluent
26
+ Cloud, Aiven or Redpanda referenced by the cluster's own workloads), auto-wire
27
+ credentials from Kubernetes Secrets, and reach brokers that are routable only
28
+ from inside the cluster through per-broker port-forwards. Everything lives in
29
+ the cluster sidebar under **Apache Kafka**: **Clusters**, **Overview**,
30
+ **Topics**, **Consumer Groups**, **Brokers** and, once an endpoint is
31
+ configured, **Schema Registry**, **Kafka Connect** and **ACLs**.
32
+
33
+ ![The Messages browser of a topic on the local Kafka fixture, dark theme](docs/screenshots/topic-messages-dark.png)
34
+
35
+ The goal is feature parity with the standalone open-source Kafka consoles,
36
+ embedded in the tool you already use for the cluster. The extension is a
37
+ from-scratch MIT implementation: it does not reuse code or UI from any of
38
+ them.
39
+
40
+ ### Status
41
+
42
+ > **SPEC-001–014 verified; v1.0.0 implementation sign-off complete.** The
43
+ > extension discovers Strimzi, generic in-cluster and workload-referenced
44
+ > external/managed Kafka (including MSK), probes PC reachability, connects via
45
+ > port-forward or Direct and reads broker/controller/topic metadata. The native
46
+ > Freelens UI is sortable/filterable, uses dedicated
47
+ > Clusters/Overview/Topics/Brokers/ConsumerGroups pages, supports manual
48
+ > endpoints and resolves TLS/no-auth, PLAIN, SCRAM and mTLS profiles from
49
+ > workload Secrets or session-only overrides. Its Topics view searches names and
50
+ > lazy-loads partition leadership, replicas, ISR/offline replicas and health.
51
+ > [SPEC-004](./docs/specs/004-resource-navigation-cluster-context.md) verifies
52
+ > stable target identity, **Clusters**, **Overview**, **Topics**, Topic
53
+ > Workspace, **Brokers**, shared caching and a secondary Connection Settings
54
+ > panel. The former primary resource Drawer is retired.
55
+ > [SPEC-005](./docs/specs/005-read-only-message-browser.md) delivers explicit
56
+ > bounded read-only **Messages Browse** and **Tail**.
57
+ > [SPEC-006](./docs/specs/006-consumer-groups-lag.md) adds **Consumer Groups**
58
+ > list and **Offsets & Lag** workspace.
59
+ > [SPEC-007](./docs/specs/007-topic-broker-depth.md) adds topic/broker
60
+ > configuration and bidirectional Topic/Consumer Group cross-links.
61
+ > [SPEC-008](./docs/specs/008-message-browser-enhancements.md) adds URL-backed
62
+ > message filters, timestamp seek and full-window reload restoration.
63
+ > [SPEC-009](./docs/specs/009-write-operations.md) adds the local-safe Produce
64
+ > and Consumer Group offset-reset workflow.
65
+ > [SPEC-010](./docs/specs/010-schema-registry.md) adds Schema Registry subjects,
66
+ > versions and Avro/Protobuf decoding.
67
+ > [SPEC-011](./docs/specs/011-kafka-connect.md) adds Kafka Connect connector
68
+ > list, detail and lifecycle. [SPEC-012](./docs/specs/012-acl-security-views.md)
69
+ > adds ACL inspection, filtering and local-safe ACL create/delete on brokers
70
+ > that authorize it. SPEC-001–014 are verified with full test traceability.
71
+ > SPEC-014 meets its three-run packaged click-to-paint SLO and pinned
72
+ > open-source reference-console browser comparison. See
73
+ > [ARCHITECTURE.md](./ARCHITECTURE.md) and the [spec
74
+ > index](./docs/specs/README.md).
75
+
76
+ Slow Kubernetes/MSK operations expose real graphical phases: discovery shows
77
+ resource checks and `x/y` workload scanning; detail shows security, connection,
78
+ broker and topic metadata. Workload targets show aggregate Kubernetes usage
79
+ rather than an arbitrary first namespace, and a reachable row opens from any
80
+ cell or the keyboard.
81
+
82
+ ## Requirements
83
+
84
+ - **Freelens >= 1.8.0.** Verified on Freelens 1.10.3, the version the
85
+ integration tests run against.
86
+ - **Kubernetes access** through the kubeconfig context Freelens uses for the
87
+ cluster. Discovery reads Strimzi custom resources, Services, Pods, Secrets
88
+ and ConfigMaps; port-forwards use the same credentials.
89
+ - **Apache Kafka.** The test fixtures run Apache Kafka 3.9 (KRaft). Brokers
90
+ are reached with the [kafkajs](https://kafka.js.org/) client over
91
+ plaintext or TLS, with no authentication, SASL/PLAIN, SASL/SCRAM or mTLS.
92
+ OAUTHBEARER and AWS IAM authentication are not supported yet.
93
+ - **Node.js** is required only when building the extension from source; it
94
+ is not needed to run it. The package is a self-contained bundle: its
95
+ runtime libraries (`kafkajs`, `@kubernetes/client-node`) are compiled into
96
+ `out/`, so Freelens loads it without installing anything extra (Freelens
97
+ does not npm-install an extension's dependencies).
98
+
99
+ ## Supported sources
100
+
101
+ | Source | Found through | Reached through |
102
+ | --- | --- | --- |
103
+ | Strimzi `Kafka` resources | CRs and broker pods | Per-broker port-forward |
104
+ | In-cluster Services | Services on the Kafka ports | Port-forward or Direct |
105
+ | External or managed Kafka | Workload env and config | Direct, when reachable |
106
+ | Manual endpoints | **Add endpoint** on Clusters | Direct, TLS optional |
107
+
108
+ Strimzi clusters are reached through the pod-DNS advertised listeners of
109
+ their broker pods; in-cluster Services are found best effort on the Kafka
110
+ ports; external or managed Kafka (Amazon MSK, Confluent Cloud, Aiven,
111
+ Redpanda, ...) is found in the bootstrap servers the workloads reference and
112
+ reached directly from your machine over a VPN or a public endpoint.
113
+
114
+ Credentials come from the cluster or from the session: SASL/SCRAM and
115
+ TLS/mTLS material from Strimzi `KafkaUser` Secrets, PLAIN, SCRAM and TLS
116
+ settings from the Secrets the workloads themselves reference, or session-only
117
+ overrides in the Connection Settings panel. Passwords are never persisted.
118
+
119
+ ## Installation
120
+
121
+ Install the extension from the Freelens **Extensions** page
122
+ (`ctrl`+`shift`+`E` or `cmd`+`shift`+`E`) by npm name:
123
+
124
+ ```text
125
+ @freelensapp/kafka-extension
126
+ ```
127
+
128
+ Alternatively, download the `.tgz` from the
129
+ [GitHub releases](https://github.com/freelensapp/freelens-kafka-extension/releases)
130
+ page and drag it into the Freelens window, or provide its path on the
131
+ Extensions page.
132
+
133
+ You can also build and pack the extension yourself, see
134
+ [Build from the source](#build-from-the-source).
135
+
136
+ ## Getting started
137
+
138
+ 1. Connect to a cluster. An **Apache Kafka** group with **Clusters**,
139
+ **Overview**, **Topics**, **Consumer Groups** and **Brokers** children
140
+ appears in the cluster's left sidebar.
141
+ 2. Open **Clusters**. It lists Strimzi, Kafka Services and external/managed
142
+ endpoints referenced by workload config. Reachable external Kafka use
143
+ Direct; Strimzi uses per-broker port-forward. **Add endpoint** connects to
144
+ a bootstrap not referenced by Kubernetes (TLS optional).
145
+ 3. Click or press Enter on a reachable row to open its full **Overview**
146
+ page. Use the row's `tune` action for session-only Connection Settings or
147
+ manual endpoint removal.
148
+ 4. Open **Topics**, filter by name and select one to inspect partition
149
+ topology and replica health. Open **Messages** inside Topic Workspace; no
150
+ records are read until **Browse** is pressed.
151
+ 5. No Kafka at hand? A few commands give you something to look at, see
152
+ [Local fixtures](#local-fixtures-kind-and-docker).
153
+
154
+ > **Safety:** discovery, reachability, port-forward and metadata/topic reads
155
+ > are read-only. Never produce messages, alter topics/configs/ACLs, commit
156
+ > offsets or mutate Kubernetes resources on a real cluster. See
157
+ > [TESTING-SAFETY.md](./TESTING-SAFETY.md).
158
+
159
+ ## Features
160
+
161
+ ### Discovery and connectivity
162
+
163
+ Explicit scanning with visible progress (resource checks, then `x/y` workload
164
+ scanning), reachability probing from your machine, and one shared connection
165
+ strategy: Direct when the bootstrap is reachable, otherwise a two-phase
166
+ connect that reads the metadata, matches brokers to pods and opens one
167
+ port-forward per broker. Sessions are bounded and reused across pages, and
168
+ resource snapshots are served stale-while-revalidate, so ordinary navigation
169
+ never repeats discovery, credential resolution or connection setup.
170
+
171
+ ### Clusters, Overview and Brokers
172
+
173
+ The **Clusters** table shows every discovered target with its source, its
174
+ reachability and aggregate Kubernetes usage. **Overview** shows the security
175
+ profile, the connection strategy, brokers, the controller and topic metadata.
176
+ **Brokers** lists the brokers with their configuration.
177
+
178
+ ### Topics
179
+
180
+ A searchable topic list that lazy-loads partition leadership, replicas,
181
+ in-sync and offline replicas and health, plus a Topic Workspace with a
182
+ Configuration tab and cross-links to the consumer groups reading the topic.
183
+
184
+ ### Messages
185
+
186
+ Bounded, read-only **Browse** and **Tail** inside the Topic Workspace, with a
187
+ byte-safe inspector for key, value, headers, timestamp and offset. Nothing is
188
+ read until you press Browse, no consumer group is created and no offset is
189
+ ever committed. Filters on key, value and headers, seek by timestamp, and
190
+ URL-backed state that survives a reload of the window. Avro and Protobuf
191
+ payloads are decoded when a Schema Registry endpoint is configured.
192
+
193
+ ### Consumer groups
194
+
195
+ A sortable and filterable group list and a per-group workspace with
196
+ **Offsets & Lag** (computed with BigInt, so large offsets stay exact) and
197
+ **Members**, with cross-links back to the topics. Aggregate health across
198
+ groups is computed by a persistent, cancellable background worker with
199
+ batched offset requests and explicit exact or lower-bound coverage.
200
+
201
+ ### Schema Registry, Kafka Connect and ACLs
202
+
203
+ Optional per-cluster endpoints (URL, TLS flag and optional basic auth, stored
204
+ in the extension settings without secrets) add the **Schema Registry** page
205
+ (subjects and versions), the **Kafka Connect** page (connector list, detail
206
+ and lifecycle) and the **ACLs** page (list and filtering) to the sidebar only
207
+ for the clusters that have them.
208
+
209
+ ### Write operations
210
+
211
+ Writes are disabled by default. A session-only write mode per target unlocks
212
+ Produce Message, consumer group offset reset, Schema Registry and Kafka
213
+ Connect management, and ACL create/delete on brokers that authorize it, each
214
+ behind an explicit confirmation. Automated tests only ever write to the local
215
+ `kind` cluster and the disposable Docker fixtures.
216
+
217
+ ### Production-scale performance
218
+
219
+ Phase-local progress with a confidence-gated ETA, a compact background Health
220
+ status with independent freshness labels, bounded lists and caches, and warm
221
+ or persisted snapshots that stay usable during background refresh and
222
+ failure. The packaged app meets a click-to-paint SLO measured over three
223
+ authorized read-only runs; the evidence is in
224
+ [docs/performance](./docs/performance/).
225
+
226
+ ## Limits
227
+
228
+ - Authentication covers TLS, SASL/PLAIN, SASL/SCRAM and mTLS. OAUTHBEARER,
229
+ AWS IAM for MSK, and credentials available only as files inside a
230
+ container are not supported yet.
231
+ - Brokers that are reachable only from inside the cluster are reached
232
+ through port-forwards to their pods; there is no relay pod, so a cluster
233
+ without port-forwardable broker pods needs a reachable endpoint.
234
+ - On the discovery-only local fixtures the Kafka pods are not real brokers,
235
+ so opening Overview fails to connect; Connection Settings stays available.
236
+
237
+ ## Development
238
+
239
+ The repository is developed spec-first, with the specs in the repository:
240
+
241
+ - [ARCHITECTURE.md](./ARCHITECTURE.md) — design, decisions, roadmap.
242
+ - [Spec index](./docs/specs/README.md) — globally unique requirements,
243
+ lifecycle and verification status, one spec per feature in
244
+ [docs/specs/](./docs/specs/).
245
+ - [SPEC-COMPLETION-WORKFLOW.md](./docs/SPEC-COMPLETION-WORKFLOW.md) — how a
246
+ spec goes from accepted to verified.
247
+ - [TESTING-SAFETY.md](./TESTING-SAFETY.md) — the non-negotiable rules for
248
+ autonomous testing against real clusters.
249
+ - [docs/connectivity-engine.md](./docs/connectivity-engine.md) — how the
250
+ redirecting socket factory + port-forward manager reach in-cluster brokers.
251
+ - [docs/discovery.md](./docs/discovery.md) — Strimzi / Service discovery +
252
+ credentials.
253
+ - [docs/overview-ui.md](./docs/overview-ui.md) — the renderer overview +
254
+ drill-in UI and its IPC flow.
255
+ - [docs/message-browser.md](./docs/message-browser.md) — group-free bounded
256
+ record Fetch and byte-safe inspector.
257
+ - [Kafka UX v3](./docs/design/kafka-ux-v3-proposal.md) — accepted
258
+ page/navigation design and complete delivery sequence.
259
+ - [SPEC-004](./docs/specs/004-resource-navigation-cluster-context.md) —
260
+ verified contract for resource pages and selected Kafka cluster context.
261
+ - [CHANGELOG.md](./CHANGELOG.md) — what each release adds and changes.
262
+
263
+ ### Local gates
264
+
265
+ Node 24.15.0 (`.nvmrc` / `mise.toml`) + `corepack pnpm`. Run the local gates
266
+ after every change:
267
+
268
+ ```sh
269
+ corepack pnpm type:check
270
+ corepack pnpm lint:check # biome (lint:fix to auto-format)
271
+ corepack pnpm build
272
+ corepack pnpm knip:check
273
+ corepack pnpm test:unit
274
+ ```
275
+
276
+ Engine integration tests run against Docker / KinD, see
277
+ [test/e2e](./test/e2e) and the `kafka:*` / `kind:*` / `itest*` scripts in
278
+ [package.json](./package.json).
279
+
280
+ ### Local fixtures (kind and Docker)
281
+
282
+ - **Discovery only** (populate the Overview table, no real brokers): deploy
283
+ the Strimzi CRD and sample `Kafka` fixtures used by the tests:
284
+
285
+ ```sh
286
+ corepack pnpm kind:disc:up # apply fake Strimzi CRD + Kafka CRs
287
+ # ... test in Freelens ...
288
+ corepack pnpm kind:disc:down # tear down
289
+ ```
290
+
291
+ The Clusters table will list the fixtures. Opening Overview will fail to
292
+ connect because the fixture pods are not real brokers; Connection Settings
293
+ remains available independently.
294
+
295
+ - **Fastest Overview + Topics test** uses a disposable host-reachable Kafka
296
+ and a zero-impact workload reference in `kind-kind`:
297
+
298
+ ```sh
299
+ # starts Kafka and creates freelens-orders (3 partitions)
300
+ corepack pnpm kafka:direct:up
301
+ # makes the bootstrap discoverable from kind-kind
302
+ corepack pnpm kind:direct:up
303
+ # Open kind-kind → Kafka → 127.0.0.1 → Topics → freelens-orders
304
+ corepack pnpm kind:direct:down
305
+ corepack pnpm kafka:direct:down
306
+ ```
307
+
308
+ Overview shows the Direct connection, broker metadata and the searchable
309
+ topic/partition detail. For the internal-only port-forward path, install a
310
+ real Strimzi Kafka in KinD and open its pod-DNS-advertised listener.
311
+
312
+ ### Assisted UI verification with Playwright MCP
313
+
314
+ For fast frame-aware exploratory UI verification, start an isolated Freelens
315
+ CDP session containing only `kind-kind`:
316
+
317
+ ```sh
318
+ corepack pnpm mcp:app
319
+ ```
320
+
321
+ Then attach a locally configured, version-pinned Playwright MCP server. This
322
+ is an optional assisted loop; focused and committed integration tests remain
323
+ mandatory. See [Playwright MCP testing](./docs/playwright-mcp-testing.md) and
324
+ [ADR-001](./docs/decisions/001-playwright-mcp-assisted-verification.md).
325
+
326
+ ## Build from the source
327
+
328
+ You can build the extension from this repository.
329
+
330
+ ### Prerequisites
331
+
332
+ Use [NVM](https://github.com/nvm-sh/nvm),
333
+ [mise-en-place](https://mise.jdx.dev/), or
334
+ [windows-nvm](https://github.com/coreybutler/nvm-windows) to install the
335
+ required Node.js version.
336
+
337
+ From the root of this repository:
338
+
339
+ ```sh
340
+ nvm install
341
+ # or
342
+ mise install
343
+ # or
344
+ winget install CoreyButler.NVMforWindows
345
+ nvm install 24.15.0
346
+ nvm use 24.15.0
347
+ ```
348
+
349
+ Install pnpm:
350
+
351
+ ```sh
352
+ corepack install
353
+ # or
354
+ curl -fsSL https://get.pnpm.io/install.sh | sh -
355
+ # or
356
+ winget install pnpm.pnpm
357
+ ```
358
+
359
+ ### Build extension
360
+
361
+ ```sh
362
+ pnpm i
363
+ pnpm build
364
+ pnpm pack
365
+ ```
366
+
367
+ One script to build and pack the extension for testing:
368
+
369
+ ```sh
370
+ pnpm pack:dev
371
+ ```
372
+
373
+ This bumps a throwaway prerelease version, builds, and writes a
374
+ `freelensapp-kafka-extension-*.tgz` into the repo root. The version bump
375
+ makes Freelens treat each rebuild as an upgrade, so re-installing actually
376
+ reloads your changes.
377
+
378
+ ### Install built extension
379
+
380
+ The tarball will be placed in the current directory. In Freelens, navigate
381
+ to the Extensions page (`ctrl`+`shift`+`E` or `cmd`+`shift`+`E`) and provide
382
+ the path to the tarball, or drag and drop the `.tgz` file into the Freelens
383
+ window. Enable it if prompted.
384
+
385
+ ### Check code statically
386
+
387
+ ```sh
388
+ pnpm lint:check
389
+ ```
390
+
391
+ or
392
+
393
+ ```sh
394
+ pnpm trunk:check
395
+ ```
396
+
397
+ and
398
+
399
+ ```sh
400
+ pnpm build
401
+ pnpm knip:check
402
+ ```
403
+
404
+ ### Testing the extension with unpublished Freelens
405
+
406
+ In the Freelens working repository:
407
+
408
+ ```sh
409
+ rm -f *.tgz
410
+ pnpm i
411
+ pnpm build
412
+ pnpm pack -r
413
+ ```
414
+
415
+ Then in the extension repository:
416
+
417
+ ```sh
418
+ echo "overrides:" >> pnpm-workspace.yaml
419
+ for i in ../freelens/*.tgz; do
420
+ name=$(tar zxOf $i package/package.json | yq -r .name)
421
+ echo " \"$name\": $i" >> pnpm-workspace.yaml
422
+ done
423
+
424
+ pnpm clean:node_modules
425
+ pnpm build
426
+ ```
427
+
428
+ ## License
429
+
430
+ Copyright (c) 2025-2026 Freelens Authors.
431
+
432
+ [MIT License](https://opensource.org/licenses/MIT)