54 Commits
Author SHA1 Message Date
hanzo-dev 62a44752f4 ci: route linux/amd64 jobs to hanzo-build-linux-amd64 ARC scale set
Claude-Session: https://claude.ai/code/session_01RFrWpXc1BsqfrFYMbyDusJ
2026-07-10 21:52:30 -07:00
07a53b8c98 protocol: embed-safe Broker.Serve() for the cloud in-process fold (#4)
Startup() was a blocking accept loop that log.Panic/os.Exit(1)d on failure and
never stored its listener, so a host could not run the Kafka adaptor in-process
nor stop it cleanly. Add Broker.Serve() error — the embed-safe form that returns
errors instead of exiting, stores the listener, and returns nil on a clean
Shutdown (which now closes ShutDownSignal + the listener so Accept unblocks).
Startup() becomes a thin fatal wrapper over Serve() so standalone main.go is
unchanged. The os import is no longer needed.

Test proves Serve() returns an error (never exits) on an unreachable PubSub.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-07 12:14:15 -07:00
z dcbde05eaf docs(brand): add hero banner v1.1.0 2026-06-28 20:33:48 -07:00
z 1f3a6aa86d chore(brand): dynamic hero banner 2026-06-28 20:33:47 -07:00
zeekay aaf2c775c6 ci: route to canonical native arcd labels [self-hosted, linux, <arch>]
Replaces non-canonical scale-set / org-prefixed labels with the
existing labels every arcd host registers with. Matches evo for
amd64 and spark for arm64. No new labels added.
2026-06-10 20:14:26 -07:00
Hanzo AI fcfc6a0f32 deps: bump Go to 1.26.4 across go.mod, Dockerfiles, GH Actions
Workspace-wide sync. luxfi/node already shipped on 1.26.4 in v1.30.6
(commit 121aca1fa9); this is the cross-repo catch-up.
2026-06-07 12:12:45 -07:00
Hanzo AI b909846f0c merge: ci/canonical-docker-build-1776995246 (-X theirs) 2026-06-01 18:10:50 -07:00
Hanzo AI 15a08b17ee go.mod: bump go directive to 1.26.3 (security advisory) 2026-05-12 21:26:54 -07:00
Hanzo AI be7282458e ci: add id-token: write to caller permissions
Required for hanzoai/.github/.github/workflows/docker-build.yml@main —
without it the workflow_call dies as startup_failure with no jobs
dispatched. Caller permissions are a CEILING.
2026-05-07 09:11:51 -07:00
Hanzo DevandGitHub 1e7e840795 ci: migrate to canonical hanzoai/.github/docker-build.yml reusable (#3) 2026-04-23 18:53:52 -07:00
Hanzo AI f7c43a4c2a ci: migrate to canonical hanzoai/.github/docker-build.yml reusable 2026-04-23 18:48:30 -07:00
Hanzo AI 4c2b94a5f0 Move admin HTTP routes to /v1/stream/ prefix, add /healthz
Admin endpoints now served under /v1/stream/{status,topics,groups}
following the /<version>/<service>/<path> convention. Root /
redirects to /v1/stream/. Added /healthz for K8s HTTP probes.
v1.0.0
2026-04-09 17:46:06 -07:00
Hanzo AI 192df077d6 chore: update dependencies 2026-04-01 14:32:24 -07:00
Hanzo Dev 43690f5c19 chore: bump Go 1.26.1 2026-03-22 14:28:54 -07:00
Zach Kelling c60460d9fd chore: clean upstream branding 2026-03-03 08:09:16 -08:00
Hanzo Dev fc477594ec chore: gitignore platform-specific compiled binaries 2026-03-03 05:32:35 -08:00
Hanzo Dev a966c13e20 chore: update Go toolchain to 1.26 2026-03-02 12:12:15 -08:00
Hanzo Dev 65e18c5fff perf: Go 1.26, BuildKit cache mounts 2026-03-02 11:56:32 -08:00
Hanzo Dev 5e3f4d808e Fix event pipeline and add admin HTTP endpoint
- Fix NATS JetStream subject mismatch: SubjectName now returns
  StreamName + ".data" to match existing stream subjects, fixing
  capture produce failures ("Unknown broker error")
- Fix OffsetFetch flexible version threshold (v6, not v8) and add
  version-aware encoding for v0-v5 (non-flexible) vs v6-v7 (flexible)
- Fix ApiVersions to use non-flexible encoding for v0-v2
- Add offset out-of-range detection in Fetch with proper error code
- Add offset validation and corruption purge in consumer offsets
- Add admin HTTP server on :9093 with /status, /topics, /groups
  endpoints for Kafka-friendly monitoring without raw NATS access
- Reduce Fetch/Heartbeat/ListOffsets request logging to DEBUG
- Set default log level to INFO
- Log RecordBatch hex on Produce for debugging
2026-02-23 16:24:18 -08:00
b62d0219b8 fix: add OCI labels to Dockerfile for GHCR repo linkage (#2)
The container package was created without a source repository link,
causing GITHUB_TOKEN to lack write_package permission. Adding the
org.opencontainers.image.source label ensures GHCR auto-links the
package to the repo on creation.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:47:48 -08:00
a42d8907d5 Fix Kafka offset-to-NATS sequence mapping for multi-record batches (#1)
The Fetch handler assumed a 1:1 mapping between Kafka offsets and NATS
sequences, which breaks when Produce stores entire RecordBatches (with
multiple records) as single NATS messages. A batch of 31 records stored
as NATS seq 1 would report BaseOffset=0, but the consumer requesting
offset 31 would look for NATS seq 32 instead of seq 2.

Changes:
- Add RecordBatch header parser to read baseOffset, lastOffsetDelta,
  and recordCount from stored batch bytes
- Produce: stamp correct Kafka baseOffset into RecordBatch before
  storing in NATS (safe: baseOffset is not covered by CRC)
- Fetch: binary search NATS sequences by parsed baseOffset to find
  the batch containing the requested Kafka offset
- Fix HighWatermark and LogStartOffset to use Kafka-level offsets
  derived from RecordBatch headers instead of raw NATS sequence counts
- Fix ListOffsets (earliest/latest) to use proper Kafka offsets
- Add per-partition mutex for safe concurrent offset assignment

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:01:02 -08:00
Hanzo Dev fdb7fd18e0 fix: set PreferredReadReplica to -1 in Fetch response
rdkafka interprets PreferredReadReplica=0 as "redirect to broker 0"
and skips all message data. Use -1 (no preferred replica) so messages
are delivered to consumers correctly.
2026-02-23 10:50:23 -08:00
Hanzo Dev 3b5cc706b6 Version-aware consumer group protocol for non-flexible Kafka versions
JoinGroup v0-v5, SyncGroup v0-v3, Heartbeat v0-v3, OffsetFetch v0-v7,
OffsetCommit v0-v7, ListOffsets v0-v6: manual decode/encode without
compact strings or tagged fields. Fixes panics when node-rdkafka
negotiates non-flexible versions.
2026-02-23 10:45:26 -08:00
Hanzo Dev 3fb4f7ccaa Fix FindCoordinator v1-v3: manual decode instead of reflection
Reflection-based Decode() uses compact format, but v1-v2 are non-flexible
(int16 strings) and v3 uses compact but not the CoordinatorKeys array
layout. Decode manually for each version range.
2026-02-23 10:40:34 -08:00
Hanzo Dev d259a4a302 Fix Dockerfile for cross-compilation on Apple Silicon
Use --platform=$BUILDPLATFORM so Go compiles natively on host arch
and cross-compiles to target via GOOS/GOARCH args instead of QEMU.
2026-02-23 10:39:04 -08:00
Hanzo Dev 1a8e6399e5 Version-aware Fetch & FindCoordinator for all Kafka protocol versions
- Fetch: non-flexible decode/encode for v0-v11, flexible for v12+
- FindCoordinator: v0 (no KeyType), v1-v2 flat non-flexible, v3 flat flexible, v4+ array
- ApiVersions: advertise MinVersion=0 for Fetch and FindCoordinator so older clients can connect
2026-02-23 10:37:00 -08:00
Hanzo Dev 7b04fa77a8 Version-aware response encoding for non-flexible Kafka protocol versions
The response encoder was always using flexible format (compact arrays, compact
strings, tagged field terminators) for ALL responses. This caused rdkafka to
reject Produce v7 responses with "BadMessage" because v7 expects non-flexible
format (int32 arrays, int16 strings, no tagged fields).

- Add EncodeNonFlexible() and PutNonFlexible() for non-flexible response encoding
- Add PutArrayLen() (int32) and PutNullableString() (int16) encoder helpers
- Make EncodeResponseBytes() auto-detect flexible vs non-flexible based on API version
- Write manual encodeProduceResponse() with per-version field handling (v7 omits
  record_errors/error_message, v2+ adds log_append_time, v5+ adds log_start_offset)
- Write manual encodeMetadataResponse() for non-flexible versions (v0-v8)
- Add encoder tests for both flexible and non-flexible response formats
2026-02-23 01:56:57 -08:00
Hanzo Dev f5fe42f819 fix: add NullableString decoder for NULLABLE_STRING fields
Kafka non-flexible NULLABLE_STRING uses 0xFFFF (-1 as int16) for null.
The existing String() decoder treated 0xFFFF as length 65535, causing
out-of-range panics on Produce v7 transactional_id (which is null).

Added NullableString() to properly handle null (-1) and empty (0) cases.
2026-02-23 01:46:57 -08:00
Hanzo Dev fe1eae571a fix: version-aware Produce request decoder for v7 (non-flexible)
Produce v7 uses non-compact encoding (int16 strings, int32 arrays/bytes)
while v9+ uses compact encoding. The decoder now branches on version,
matching the same pattern as the Metadata decoder fix.
2026-02-23 01:43:39 -08:00
Hanzo Dev eb9fd0d623 fix: client_id is always int16 NULLABLE_STRING in request headers
Per Kafka protocol spec, request header v2 (flexible) uses the same
int16-prefixed NULLABLE_STRING for client_id as header v1. Only the
TAG_BUFFER is added after client_id in v2. Previous commit incorrectly
read client_id as compact string (uvarint) for flexible requests.

Also add manual Metadata request decoder that handles both v4 and v12
body formats, and null client_id test case.
2026-02-23 01:40:42 -08:00
Hanzo Dev 3c93cf1b17 fix: handle flexible/non-flexible Kafka protocol headers (KIP-482)
- ParseHeader now detects flexible version requests per API key/version
- Flexible headers: compact client_id (uvarint) + tagged fields skip
- Non-flexible headers: int16 client_id, no tagged fields
- Add manual Metadata request decoder for v4 and v12 formats
- Add panic recovery in HandleConnection to prevent crashes
- Add ParseHeader unit tests for both header formats
2026-02-23 01:36:18 -08:00
Hanzo Dev f9cd4b77e2 fix: skip tagged fields in request headers instead of panicking
rdkafka sends ApiVersions v3+ requests with tagged fields in the
header. The stream service was panicking on non-empty _tagged_fields,
causing crash loops when used with PostHog's capture service.

Now properly skips tagged fields (varint-encoded tag + compact bytes)
rather than crashing.
2026-02-23 01:09:41 -08:00
Hanzo Dev 392fd53c98 docs: update LLM.md with deployment details and stream replica count 2026-02-23 00:47:35 -08:00
Zach Kelling 666cc1a06a pin Dockerfile to linux/amd64 for K8s compatibility 2026-02-22 14:38:12 -08:00
Zach Kelling 74858afc40 rename to Hanzo Stream (github.com/hanzoai/stream)
- Module path: github.com/hanzoai/kafka -> github.com/hanzoai/stream
- Docker image: ghcr.io/hanzoai/stream
- Binary: hanzo-stream
- All imports updated across 20+ Go files
2026-02-22 14:24:12 -08:00
Zach Kelling 69a084a537 decouple Docker build from integration tests
Integration tests (e2e, cluster) need protocol debugging and should
not block image publishing. Build-and-push now only depends on
lint-and-vet (build, vet, staticcheck). Integration tests still run
but with continue-on-error.
2026-02-22 13:59:40 -08:00
Zach Kelling 3a9526a39b add consumer timeouts to prevent test hangs in CI
- Add --timeout-ms 30000 to all kafka-console-consumer.sh calls
- Add startup sleep in e2e TestMain for PubSub connection
- Add -timeout 5m to go test invocations in CI
- Run both e2e and cluster tests in CI
2026-02-22 13:57:04 -08:00
Zach Kelling b7e10f2c2f update LLM.md with PubSub/Hanzo Stream branding and K8s deployment info 2026-02-22 13:41:14 -08:00
Zach Kelling 8e7cbf4724 fix staticcheck warnings: time.Since, redundant returns 2026-02-22 13:40:33 -08:00
Zach Kelling e02e7fda1b rebrand to Hanzo Kafka: thin Kafka wire protocol gateway over Hanzo PubSub
- Rebrand from MonKafka to Hanzo Kafka (github.com/hanzoai/kafka)
- Replace Raft/Serf/local storage with Hanzo PubSub (NATS JetStream)
- Add pubsub/ package: stream management, offset KV, publish/fetch
- Rewrite all protocol handlers to delegate to PubSub
- Simplify config: remove LogDir, Raft, Serf fields; add PubSub fields
- Delete raft/, state/, storage/ packages (replaced by PubSub)
- Add Dockerfile for ghcr.io/hanzoai/kafka image
- Add CI/CD workflow: lint, vet, test with PubSub, Docker build+push
- Rewrite e2e and cluster tests for stateless PubSub-backed broker
2026-02-22 13:38:22 -08:00
moncef.abboud 089e9e66b7 remove reflection for Produce/Fetch (too slow) + minor tweaks
Signed-off-by: moncef.abboud <moncef.abboud95@gmail.com>
2025-04-09 17:50:13 -05:00
moncef.abboud f104b7c14d added some error messages 2025-03-01 11:22:27 -06:00
moncef.abboud b5b0eb3396 WIP: add cluster mode using Raft and Serf 2025-02-23 18:13:12 -06:00
moncef.abboud 6a14cfaa08 add basic error support 2025-01-25 12:42:28 -06:00
moncef.abboud b038780cae add compression support 2025-01-18 10:23:35 -06:00
moncef.abboud 300ceaaab6 use reflection for deserialization 2025-01-04 17:12:00 -06:00
moncef.abboud bff9ecae3c use reflection for serialization 2025-01-03 21:11:40 -06:00
moncef.abboud bf632d6cfb add CI 2025-01-02 23:08:27 -06:00
moncef.abboud a01fd55c91 add __consumer-offsets 2025-01-02 15:42:14 -06:00
moncef.abboud 20020ef96c basic logging levels 2024-12-30 09:23:36 -06:00