| KIP-8 |
Replica Fetcher |
Done |
InterBrokerApiHandler.UpdateMetadata |
| KIP-98 |
Exactly-Once Delivery (idempotent + txns) |
Done |
TransactionCoordinator, Kip892TransactionDefenseTests, six TransactionTests (commit, abort, isolation, mixed, fencing, consume-process-produce) round-trip via Confluent.Kafka. The five EOS RPCs (22, 24, 25, 26, 28) dispatch through the SurgewaveBroker.ProcessRequestAsync fast-path switch. |
| KIP-113 |
Replicas to log dirs |
Wired (rejects) |
Surgewave has a single data dir per broker, so AlterReplicaLogDirs rejects every partition with LogDirNotFound. DescribeLogDirs returns the single LogDirResult with per-partition sizes. |
| KIP-455 |
Partition reassignment |
Done |
PartitionReassignmentManager with full 4-state machine (Pending → Adding → Syncing → Completing → Completed); wired through ClusterAdminHandler for AlterPartitionReassignments / ListPartitionReassignments. |
| KIP-460 |
Admin leader-election RPC |
Done |
ClusterAdminHandler → ClusterController.ElectLeaderAsync with three-stage fallback (Preferred → ISR → Unclean). |
| KIP-496 |
Allow consumers to delete offsets |
Done |
ConsumerGroupCoordinator.HandleOffsetDelete — conservative read of GROUP_SUBSCRIBED_TO_TOPIC for groups with active members. |
| KIP-516 |
Topic Identifiers |
Done |
Metadata/Fetch/Produce carry Uuid topic IDs |
| KIP-554 |
SCRAM credential admin RPCs |
Done |
SecurityApiHandler + ScramCredentialStore. Two stores (SHA-256 + SHA-512) stand up in-memory when SCRAM is in SaslMechanisms. The wire RPC is the canonical provisioning path. |
| KIP-595 |
KRaft (ZK-less consensus) |
Done |
RaftApiHandler, 5 quorum APIs (52–55, 59) |
| KIP-664 |
DescribeProducers |
Done |
TransactionCoordinator.HandleDescribeProducers projects ProducerStateManager state per (topic, partition). |
| KIP-714 |
Client Telemetry Reporting |
Done (wire + log/meter ingestor + topic sink) |
TelemetryApiHandler + ITelemetryIngestor. Default LoggingTelemetryIngestor logs and meters every push. Optional TelemetryTopicSink mirrors raw OTLP MetricsData blobs to an internal topic. Server-side decode of the OTLP proto into per-metric Meter instruments remains a future enhancement. |
| KIP-848 |
Consumer Group v2 |
Done |
ConsumerGroupV2*, Kip848WireTests, Kip848ConsumerProtocolTests |
| KIP-853 |
Dynamic Raft Voter Changes |
Wire bound + foundation in place — semantics not implemented |
RPCs 80/81/82 advertise and bind to a polite-rejection handler. Pre-validation rejects malformed requests with InvalidRequest (42). Foundation building blocks: RaftConfiguration immutable record + monotonic ConfigurationSequence, reserved MetadataCommandType.VoterChange enum slot. Implementation plan: internal voter-changes design doc. |
| KIP-892 |
Transaction Coordinator Schemas |
Done |
Kip892TransactionDefenseTests |
| KIP-894 |
Tiered Storage (Remote Log) |
Partial |
RemoteLogSegmentState, IRemoteStorageProvider plug-points exist; remote fetch path is fenced behind config |
| KIP-895 |
KRaft broker registration v2 |
Done |
ClusterMembershipHandler (62, 63, 64) |
| KIP-903 |
Fetch v15 (replicaId removed) |
Done |
FetchRequest.Reader flexible-version parsing |
| KIP-932 |
Share Groups (queue-style) |
Done |
ShareGroupApiHandler, ShareGroupCoordinator, Kip932WireTests |
| KIP-936 |
SASL/OAUTHBEARER on the wire |
Done |
OAuthBearerAuthenticator + JwksTokenValidator, wired into SaslAuthenticator; OIDC discovery + direct JWKS, audience/issuer/principal-claim configurable; 12 unit tests + 5 integration tests with an in-process IdP fixture. |
| KIP-966 |
Paginated DescribeTopicPartitions |
Done |
MetadataApiHandler.HandleDescribeTopicPartitions honours ResponsePartitionLimit + StartingCursor; emits NextCursor when truncated. |
| KIP-985 |
Reverse range iteration |
Done |
IReadOnlyKeyValueStore.ReverseAll() / .ReverseRange() |
| KIP-994 |
Transactional ListTransactions filters |
Done |
Kip994ListTransactionsFiltersTests (8 semantic) + Kip994ListTransactionsWireTests (4 wire-roundtrip across v0/v1/v2). Pathological-regex defence ((a+)+$ Cox bait) caught by MatchTimeout plus a RegexMatchTimeoutException swallow. |
| KIP-1071 |
Streams Groups (topology-aware) |
Done |
StreamsGroupApiHandler, StreamsGroupCoordinator |
| KIP-1106 |
ListConfigResources for KIP-714 |
Done |
TelemetryApiHandler.HandleListConfigResources returns the configured metric subscriptions when telemetry is enabled. |
| KIP-1152 |
TransactionalIdPattern filter |
Done |
Wire-parsed at v2+; the regex DoS defence (timeout + exception swallow) fires on this code path too. |
| KIP-1242 |
ApiVersions v5 (ClusterId/NodeId + REBOOTSTRAP_REQUIRED) |
Done |
ApiVersionsRequest.cs reads + writes the v5 ClusterId (nullable compact string) + NodeId (int32) fields so the trailing tagged-fields varint stays aligned. MetadataApiHandler.HandleApiVersions triggers REBOOTSTRAP_REQUIRED (129) when a v5+ request carries a non-null ClusterId that doesn't match the broker's actual cluster ID OR a NodeId (!= -1) that doesn't match the broker's BrokerId. v4 requests don't carry these fields and are never rejected. Kip1242ApiVersionsV5Tests pins the wire framing + error-code value; Kip1242RebootstrapTriggerTests (5) pins the handler-side trigger (match passes, null/-1 passes, ClusterId mismatch → Rebootstrap, NodeId mismatch → Rebootstrap, v4 ignores the fields). |
| KIP-1226 |
Share-partition lag in DescribeShareGroupOffsets v1 |
Done |
DescribeShareGroupOffsetsResponse.DescribePartitionResult.Lag (int64, default -1) on the wire, v1-gated in both WriteTo and ReadFrom. ShareGroupCoordinator.HandleDescribeShareGroupOffsets populates it via log.HighWatermark - group.StartOffsets[key] (floor 0) in both code paths — explicit topic list AND "all subscribed topics" fallback. Kip1226ShareGroupLagTests pins v0 drops the field (no framing drift) and v1 round-trips the lag value. |
| KIP-1222 |
Renew acknowledgements in ShareAcknowledge v2 |
Wire pinned; lease-renew semantics deferred |
ShareAcknowledgeRequest carries the v2 IsRenewAck bool plus the new AcknowledgeType = 4 (Renew) value in the int8 array. ShareAcknowledgeResponse carries AcquisitionLockTimeoutMs (int32, v2+, ignorable). Both are v2-gated in WriteTo and ReadFrom. The actual lease-renew handling inside ShareGroupCoordinator is a follow-up — Surgewave currently treats a Renew ack as a no-op pass-through, which is wire-safe but doesn't actually extend the in-flight lock. Kip1222ShareAckRenewTests pins the v2 round-trip (IsRenewAck + AcknowledgeType=4) and a v1 regression that the v2 fields stay off the wire. |
| KIP-1319 |
Topic IDs in TxnOffsetCommit v6 |
Done |
TxnOffsetCommitRequest/Response model refactored from name-keyed Dictionary to List<TxnOffsetCommitTopic> with both Name? (v0-5) and TopicId (v6+). WriteTo/ReadFrom pick the right wire field per version. Both TransactionCoordinator and ClusteredTransactionCoordinator resolve TopicId → Name via LogManager.GetTopicMetadataById at v6 entry and return UNKNOWN_TOPIC_ID per partition when unresolvable; pre-v6 paths back-fill TopicId so the response can carry it at v6 if needed. Advertised version bumped to 6. Kip1319TxnOffsetCommitV6Tests pins v5 (Name) and v6 (TopicId) wire framing for both request and response. |
| KIP-1251 |
Per-partition assignment epochs + per-partition fence-check (CGv2 OffsetCommit) |
Done |
TopicPartitionAssignment carries AssignmentEpochs: List<int>? aligned with Partitions; TargetAssignmentComputer.ApplyAssignment snapshots the previous (TopicId, Partition) → epoch map before recomputing so partitions that stay with the same member keep their stable per-partition epoch (newly assigned ones get the current GroupEpoch). On the commit-fence side, ConsumerGroupV2Coordinator.IsPartitionAssignmentValid does the per-partition check; CommitOffsetsForV2Group calls it per partition and emits STALE_MEMBER_EPOCH for partitions where the request's member epoch is below the partition's assignment epoch. The pre-flight ValidateMemberForOffsetOperation no longer fences on memberEpoch < member.MemberEpoch — that decision is deferred to the per-partition check so the KIP's motivating case (old member commits for partitions it still holds across a rebalance) actually works. Future-epoch claims still get FencedMemberEpoch at the pre-flight. Legacy persisted state without AssignmentEpochs falls back to strict group-level equality. Kip1251PerPartitionEpochTests (4) pins the assignor population; Kip1251FenceCheckTests (8) pins the fence-check (current/older/future epochs, owned/non-owned partitions, unknown group/member, legacy-state fallback, pre-flight loosening). All 869 broker tests continue to pass. |
| KIP-1240 |
Share-group configs (share.delivery.count.limit, share.partition.max.record.locks, share.renew.acknowledge.enable) |
Renew-gate enforced + admin-wired; delivery-count / max-locks enforcement still follow-up |
ShareGroupState carries the three configs with the upstream defaults (5 / 2000 / true). share.renew.acknowledge.enable is enforced inline in ShareGroupCoordinator.ProcessAcknowledgementBatches: any RENEW (AckType=4) in an incoming batch returns INVALID_REQUEST per partition when the gate is closed, checked up-front so the rejection takes precedence over QueueView absence. MaxDeliveryCount and MaxRecordLocks are forward-compat state today — Surgewave's QueueView has no per-partition lock-cap or archive-on-overflow logic yet. Admin-side wire-up landed in a follow-up commit: IncrementalAlterConfigsRequest with ResourceType.Group (32) routes through ConfigApiHandler → ShareGroupCoordinator.SetShareGroupConfig, with upstream clamps enforced (delivery.count.limit ∈ [2,10], max.record.locks ∈ [100,10000]). DELETE op restores the upstream default. Kip1240ShareGroupConfigTests (5) pins the state + renew-gate behaviour; Kip1240IncrementalAlterConfigsTests (6) pins the admin path (set persists, clamps enforced, DELETE restores default, unknown config name → InvalidConfig, ValidateOnly is non-mutating). |
| KIP-1196 |
Coordinator-internal buffer-pool caps (group.coordinator.cached.buffer.max.bytes, share.coordinator.cached.buffer.max.bytes) |
Config captured; buffer-reuse pool follow-up |
BrokerConfig.GroupCoordinatorCachedBufferMaxBytes and BrokerConfig.ShareCoordinatorCachedBufferMaxBytes carry the two new broker-level caps with the upstream defaults (1 MiB + 12-byte log-record overhead) and a [Range(524288, int.MaxValue)] validator matching the upstream atLeast(512 * 1024) lower bound. Buffer-reuse pool wiring inside the coordinators is a follow-up — Surgewave allocates per-write today, which is fine for the current throughput envelope but leaves a few % on the table at sustained high-rate group-metadata churn. Kip1196CoordinatorBufferConfigTests (8) pins the property names by reflection (so a future rename can't silently detach the test from KIP-1196) plus the defaults, the RangeAttribute lower bound, custom-value acceptance, and below-bound validation failure for both properties. |
| KIP-1263 |
Coordinator background threads + assignment intervals (group.coordinator.background.threads, group.{consumer,share,streams}.assignment.interval.ms) |
Config captured; assignment-throttle + background-pool wiring follow-up |
BrokerConfig.GroupCoordinatorBackgroundThreads (default 2, atLeast(1)) plus three matching assignment-interval properties (one per group type, default 1000 ms, atLeast(0)). Surgewave's TargetAssignmentComputer already runs only on material membership/subscription change, so the time-based assignment-interval gate is a follow-up rather than a critical gap — Surgewave is less prone to the upstream thrash that motivated this KIP. Background-thread pool wiring for regex-subscription updates is also a follow-up: today the regex path runs inline on the heartbeat thread. Kip1263CoordinatorTuningConfigTests (11) pins property names by reflection, the upstream defaults (2 / 1000 / 1000 / 1000), the lower bounds (1 / 0 / 0 / 0), and that below-bound values fail Validator.TryValidateProperty. |
| KIP-1161 |
Stricter LIST-type config validation + num.replica.fetchers >= 1 |
Done |
Two pieces: (a) DynamicBrokerConfig.ValidateConfigValue enforces num.replica.fetchers >= 1 (the new lower bound — pre-1161 a value of 0 silently disabled replica fetching). Surgewave promotes the config to DynamicConfigKeys so admins can tune it via IncrementalAlterConfigs with the bound checked at set-time. (b) BrokerConfig.Validate ships a generic ValidateListConfig helper that runs against the four LIST-type properties (Security.SaslMechanisms, Security.Users, Security.SuperUsers, Security.OAuth2.AllowedAlgorithms): null/blank entries reject outright; duplicate entries are deduplicated in-place with the dropped count surfaced as a warning-shaped error. The per-config comparer matters — SaslMechanisms/AllowedAlgorithms are OrdinalIgnoreCase (PLAIN == plain, RS256 == rs256), Users/SuperUsers are Ordinal (distinct credentials per case-distinct username). Kip1161ListConfigValidationTests (8) pins all six branches: num.replica.fetchers accepts/rejects 0/-3/4, blank entry rejected, duplicates deduplicated, no-duplicates passes clean, case-sensitivity preserved per-config. |