n57cqmu7kjf0oqf11e34gufor0odjj5p · 111 rows
| id | content_hash | title | description | design | acceptance_criteria | notes | status | priority | issue_type | assignee | estimated_minutes | created_at | created_by | owner | updated_at | closed_at | closed_by_session | external_ref | spec_id | compaction_level | compacted_at | compacted_at_commit | original_size | sender | ephemeral | wisp_type | pinned | is_template | mol_type | work_type | source_system | metadata | source_repo | close_reason | event_kind | actor | target | payload | await_type | await_id | timeout_ns | waiters | hook_bead | role_bead | agent_state | last_activity | role_type | rig | due_at | defer_until | no_history | started_at | is_blocked |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tarantool-etcd-axs | a0c9a9219a53e6fa60ca977b86cbde3b627bc6e616f64b0c292af4d186b91633 | Learner: rafthttp peer transport over nghttp2 | Implement etcd's rafthttp peer transport so the cluster can stream the raft log to us. Endpoints (HTTP/2, port 2380): /raft (pipeline POST), /raft/stream/message/<local-id> and /raft/stream/msgapp/<local-id> (long-lived streams), /raft/snapshot (snapshot receive, separate phase). Must: open/maintain streams to each peer, receive MsgApp/MsgHeartbeat/MsgSnap, send MsgAppResp/MsgHeartbeatResp back, do etcd peer version negotiation (X-Etcd-Cluster-ID, X-Server-Version, X-Raft-To/From headers). Reuse lib/nghttp2 for HTTP/2 framing. Raw message bodies are gogoproto-encoded raftpb.Message — decode lives in the proto-decode phase; this phase just moves bytes + manages stream lifecycle. | rafthttp reference in etcd/server/etcdserver/api/rafthttp/. Header contract is strict — mismatched cluster-id/version closes the stream. | open | 2 | task | NULL | NULL | 2026-05-20T06:45:14Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-b08 | e3928051dd644ec2d3c70348320e479a23d4e425c4f5776f5a2cbbfc3d571607 | Phase 5g — Auth/Cluster/Maintenance/Lock/Election option coverage | Per-option density on the remaining v3 services. Low priority — each surface is small and the existing files already cover the canonical paths; spot-fill only what option coverage actually reveals. Run after Phase 5f. | Spot-fill tests added where an unaddressed option diverges between cells; documented as a known gap otherwise. | Source: docs/TODO.md "Open / Conformance matrix — Phase 5 option coverage". | open | 3 | task | NULL | NULL | 2026-05-19T13:34:10Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | ||||||||||||||||||||||
| tarantool-etcd-bdf | bfc4038d48324b7c9fc5e533914f732797d0d1bb9a7f9d09560a51dc7cce0722 | gRPC server reflection | Roadmap P1. Implement the gRPC reflection service (grpc.reflection.v1alpha / v1) so tools like grpcurl and etcdctl-adjacent tooling can discover services/methods without local .proto files. Serve the descriptors from the codegen-emitted schema tables. | Roadmap-only item; not tracked before. | open | 1 | feature | NULL | NULL | 2026-05-20T06:55:23Z | Eugene Blikh | bigbes@gmail.com | 2026-05-20T06:55:23Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-bg4 | 4f65298830b799a0aa90d2dadbcb7f92f52d144db8dc119673c85221d1f7ffba | iproto-verify: etcd_role_list vs Auth.RoleList | Add Lua testkit verification for etcd_role_list (mirrors gRPC Auth.RoleList). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_role_list(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:14Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:14Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-bol | 6e7729d0a88e476af22e1b9544083fc6358ea78739d3f4496e69e263f342d93f | iproto-verify: etcd_role_add vs Auth.RoleAdd | Add Lua testkit verification for etcd_role_add (mirrors gRPC Auth.RoleAdd). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_role_add(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:12Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:12Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-boq | 78f7ab0f980e3e418ac85b10e54290632eb565a339b43e58c52e1512d179539a | Learner: raft state machine (follower/learner subset) | Minimal raft state machine for a non-voting learner. Track currentTerm, commitIndex, lastApplied, and the membership ConfState. Handle: MsgApp (append entries, advance commit), MsgHeartbeat (advance commit, reply), MsgSnap (hand to snapshot phase). Explicitly DROP/reject MsgVote/MsgPreVote and never campaign or transition to candidate/leader (learners can't vote or be elected). Apply ConfChange entries to track membership (including our own promotion away from learner -> would flip behavior, out of v1 scope). No proposal path. This is the brain that decides which entries are committed and ready to apply; the apply loop is a separate phase. | We are NOT reimplementing etcd's full raft — only the receive/commit/apply path a learner needs. Election, log compaction-on-leader, ReadIndex coordination all out of scope. | open | 2 | task | NULL | NULL | 2026-05-20T06:45:15Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-bq8 | 384f622c395002fdc1fa6c43c9005f80116e1c4c08c9aed8828a8671b4293a6b | iproto-verify: etcd_lease_revoke vs Lease.LeaseRevoke | Add Lua testkit verification for etcd_lease_revoke (mirrors gRPC Lease.LeaseRevoke). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/lease. Call shape: local resp = etcd_lease_revoke(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:53:59Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:53:59Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-buq | 9370d11c13a9d704f0b6e3f0241d2513428257a7e3278aacfed07ddb5818c965 | Drop stale TODO-item-14 comment in app/etcd/json.lua | app/etcd/json.lua:621 has a stale comment: "/v3/election/observe — gated on TODO item 14". TODO item 14 closed in docs/TODO.md (the Election Observe broadcast is implemented; STREAM_HANDLERS at line 427 includes /v3/election/observe). The comment is now misleading; rewrite it to describe what the fallback branch actually catches (a streaming PATH without a handler registered) and remove the historical reference. | Comment at app/etcd/json.lua:621 no longer references TODO item 14 or implies /v3/election/observe is unimplemented. | Backlog. Found while auditing TODOs for the bd port on 2026-05-19. | open | 4 | task | NULL | NULL | 2026-05-19T13:34:52Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T13:34:52Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-cc7 | 08a9119b866b0edcef671ef29415ba1d060bc828197979f54344268411b4c784 | Conformance: bump etcd backend from 3.6 to 3.7 | tests/conformance/go.mod pins go.etcd.io/etcd/{api,client/pkg,client,server,tests}/v3 at v3.6.0, so every 'etcd' conformance cell measures us against 3.6 behavior. etcd 3.7 is now released and is what new deployments will run. Bump the pins to v3.7.0 and fix whatever the suite surfaces. Known-relevant 3.7 changes that touch the harness rather than our server: - clientv3 no longer honors the deprecated grpc.WithBlock dial option (client creation is non-blocking) — harness/dial.go may rely on dial-blocking for readiness. - Go 1.26.4 build requirement. - Protobuf overhaul: golang/protobuf + gogo/protobuf -> google.golang.org/protobuf, plus grpc-middleware v2. May move types the suite imports. - v2 discovery/request/client packages removed (we never used them). - embed.Etcd surface may have shifted; experimental flags were all removed in favor of Kubernetes-style feature gates. Any behavior divergence this uncovers gets its own issue + a knownGaps entry, not a silent skip. | cd tests/conformance && go test -count=1 ./... green against both backends on both wires with v3.7.0 pins; each new divergence has an issue and a gaps.go entry referenced from docs/TODO.md. | open | 2 | task | NULL | NULL | 2026-07-17T11:30:04Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T11:30:04Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-cnj | ed489cb32430e8d6cd2ea3b91464291e41a9c603992a7c8baf680dd56c313931 | [epic] Raft-learner replica — join an etcd cluster as a non-voting member | Attach this server to a real etcd cluster as a Raft *learner* (non-voting member), receiving the replicated log over etcd's internal peer protocol (rafthttp) and applying it into our etcd_* spaces. Unlike the Watch-mirror route (tarantool-etcd-7ey), a learner is in the cluster's membership view (MemberList shows it), sees auth/lease/cluster/alarm state in the log automatically, and avoids the Watch compaction-resync gap. Cost is ~60-70% of full-member work, NOT 20%: the election state machine, proposal path, leader responsibilities, and snapshot *send* drop off, but the rafthttp transport, log applier, and snapshot *receive* (bbolt parse) all remain. We track etcd-INTERNAL protos (raftpb.Message, etcdserverpb.InternalRaftRequest) — stable-ish but not a public contract; release cadence binds to upstream etcd versions. Decision context (chat 2026-05-20): user explicitly chose the learner path over the Watch mirror. This epic is the alternative to 7ey, not a child of it. Phasing is learner-first and bottom-up: config -> transport -> proto decode -> state machine -> apply loop -> snapshot receive -> durability -> membership handshake -> conformance. Split into child issues below. | Surface map: peer endpoints /raft, /raft/stream/message/<id>, /raft/stream/msgapp/<id>, /raft/snapshot on port 2380. Reuses our nghttp2 HTTP/2 layer for the transport and our pure-Lua pb engine for the gogoproto schemas. Easiest correctness oracle: tests/conformance harness can SpawnEtcd then MemberAddAsLearner us. | open | 2 | feature | NULL | NULL | 2026-05-20T06:39:59Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-cpp | 51598282012a458cd2be1c01fc8c7326fd8c8624f667d400c44e1d56412c5f5b | C-runtime + C-compile-time protobuf path (3-5x speedup) | Roadmap P1. The pure-Lua / pb protobuf encode/decode is a hot path; a C runtime (and compile-time generated codecs) for protobuf is expected to bring 3-5x throughput, approaching Go-level. Scope: evaluate/extend the pb engine with a C backend, generate per-message C codecs at compile time, wire into the decode/encode boundary. Interacts with the JIT-disabled-after-box.cfg reality on this build. | Roadmap-only item; not tracked before. | open | 1 | feature | NULL | NULL | 2026-05-20T06:55:24Z | Eugene Blikh | bigbes@gmail.com | 2026-05-20T06:55:24Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-cz5 | 4624dbf6ad6bf8e90df4dfb60839daf2c9b81d1490c3dccf619f343a0eef92fc | iproto-verify: etcd_maintenance_move_leader vs Maintenance.MoveLeader | Add Lua testkit verification for etcd_maintenance_move_leader (mirrors gRPC etcdserverpb.Maintenance.MoveLeader). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/maintenance. | Epic tarantool-etcd-w8q. Blocked on the matching impl issue. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:42Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-dkr | 36433e1a02770d7b48365cfd48bf7f0f3db1f7e2f287b723f41083bd7ff61377 | Alternative transports for gRPC | Roadmap P2 (later). Support gRPC over transports other than the current nghttp2/TCP path (e.g. unix sockets, or alternate HTTP/2 stacks). Exploratory; depends on the http2-rock extraction landing first. | Roadmap-only item; not tracked before. | open | 2 | feature | NULL | NULL | 2026-05-20T06:55:26Z | Eugene Blikh | bigbes@gmail.com | 2026-05-20T06:55:26Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-dmt | c018e2fea002b9ae10b51cd9b69a7fc6e4137e1abddda5894b9874aea50df95f | iproto-verify: etcd_election_resign vs Election.Resign | Add Lua testkit verification for etcd_election_resign (mirrors gRPC v3electionpb.Election.Resign). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/election. | Epic tarantool-etcd-w8q. Blocked on the matching impl issue. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:53Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-g1a | 94cc76ee0c10feae7cdcc327b843bb2cd907d8b2e7190c64ce7f199385cb4caa | iproto-impl: etcd_member_list vs Cluster.MemberList | Wrap the existing handler cluster.member_list (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberList) as a Lua global etcd_member_list callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_list', wrap('cluster', 'member_list')) under the appropriate service block; append 'etcd_member_list' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Cluster.MemberList returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_member_list is callable from net.box:call('etcd_member_list', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/cluster.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:25Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-gz4 | ce1604ad8990ae56710064076900a30bc028c5a592327c484f437c820d40360c | iproto-verify: etcd_put vs KV.Put | Add Lua testkit verification for etcd_put (mirrors gRPC KV.Put). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/kv. Call shape: local resp = etcd_put(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:53:53Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:53:53Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-h8r | 864b7efe5edb39f6670b5bb0ca34accb55dcf6beba77a46d7fd987280df09847 | iproto-verify: etcd_election_observe vs Election.Observe | Add Lua testkit verification for etcd_election_observe (mirrors gRPC v3electionpb.Election.Observe). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/election. | Epic tarantool-etcd-w8q. Blocked on the matching impl issue. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:51Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-hco | a75a35cc4e55aca16758bcde37bde3575cc73d8106697aa8e8274c5013dfdb31 | iproto-impl: etcd_election_observe vs Election.Observe | Wrap the existing handler election.observe (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Observe) as a Lua global etcd_election_observe callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_observe', wrap('election', 'observe')) under the appropriate service block; append 'etcd_election_observe' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Election.Observe returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_election_observe is callable from net.box:call('etcd_election_observe', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/election.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:50Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-hlx | 629cacff048485b7bfdb7696ef646a8c092fc87f720e2f43caae3e2bfd8170ae | Replica route: watch-tail live sync | After bootstrap, open a clientv3 Watch from the bootstrap watermark+1 over the whole keyspace and apply every event (PUT/DELETE) into the etcd_* spaces, advancing the local synced watermark per event header. Must handle: - Progress notifications (WithProgressNotify) to advance the watermark even when idle, and detect staleness. - ErrCompacted (code 11): upstream compacted past our position -> trigger a re-bootstrap (tarantool-etcd child) then resume. - Reconnect/backoff on upstream Unavailable; resume from last applied revision. - Ordering: apply events in revision order; the local revision counter tracks upstream mod_revision (see revision-alignment child). This is the steady-state engine of mirror mode. | ErrCompacted=11 and progress-notify semantics are the ones we already understand from conformance work (see clientv3 quirks memory). | open | 2 | task | NULL | NULL | 2026-05-20T06:17:55Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-huo | 96dcd8d31ebf9f5f56da997ac7d459e417b024ed5bd339a4a5c33c469b4e96c1 | etcd /metrics compatibility — match upstream Prometheus metric names + endpoint | Expose a Prometheus /metrics endpoint whose metric names, label sets, and types match upstream etcd's, so existing etcd Grafana dashboards, recording rules, and alerts work unchanged against tarantool-etcd. This is the compatibility layer on top of the underlying metrics integration (tarantool-etcd-unw): map our collected operational stats onto etcd's canonical series — e.g. etcd_server_has_leader, etcd_server_leader_changes_seen_total, etcd_mvcc_db_total_size_in_bytes, etcd_server_proposals_committed_total, grpc_server_handled_total{grpc_method,grpc_code}, etcd_network_peer_round_trip_time_seconds, etcd_debugging_mvcc_keys_total, etc. Scope to nail down: which series are meaningful for a Tarantool backend vs which must be emitted as constants/stubs to satisfy dashboards, the /metrics text-format exposition path (does it ride the JSON gateway or a dedicated listener), and a conformance check that scrapes both real etcd and tarantool-etcd and diffs the metric name/label surface. | open | 2 | feature | NULL | NULL | 2026-05-20T19:08:45Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | ||||||||||||||||||||||||
| tarantool-etcd-hx9 | 83339a7afd9423290ef9d2cd3efe2cd40957688e945103b127b1b1bbb8e52b4a | iproto-impl: etcd_member_remove vs Cluster.MemberRemove | Wrap the existing handler cluster.member_remove (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberRemove) as a Lua global etcd_member_remove callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_remove', wrap('cluster', 'member_remove')) under the appropriate service block; append 'etcd_member_remove' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Cluster.MemberRemove returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_member_remove is callable from net.box:call('etcd_member_remove', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/cluster.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:21Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-iij | 291c145ebcd3fb5899f03f83ed0a7ad011df3459d5a8ed30498483aef3cd726f | iproto-verify: etcd_lock vs Lock.Lock | Add Lua testkit verification for etcd_lock (mirrors gRPC Lock.Lock). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/lock. Call shape: local resp = etcd_lock(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:17Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:17Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-iz4 | 362238cde2d5629a32ed5166d55ec1085d0b4eb2cc0715b0eab59a0ab734967f | iproto-verify: etcd_role_grant_permission vs Auth.RoleGrantPermission | Add Lua testkit verification for etcd_role_grant_permission (mirrors gRPC Auth.RoleGrantPermission). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_role_grant_permission(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:15Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:15Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-j1c | d72af58dd67917cd0d6f45c09ebc8410746a5a5fa3ce0f2fc547a0845aa4d6da | /debug/pprof/heap — pprof-shape converter on top of /debug/memprof | /debug/memprof ships the raw Tarantool memprof binary trace. Open work: a pprof-shape converter — pure-Lua parser for the memprof binary, aggregate events by allocation site, emit a four-dimension perftools.profiles.Profile (alloc_objects/count, alloc_space/bytes, inuse_objects/count, inuse_space/bytes — Go heap profile shape). Implementation sketch: 1. Pure-Lua parser for the memprof binary format (header magic + tagged event stream: alloc / realloc / free / symtab). Reference is tools/memprof.lua + tools/utils/binreader.lua in upstream tarantool/tarantool (not bundled with the homebrew binary). 2. Aggregate into (stack_key → {alloc_objs, alloc_bytes, inuse_objs, inuse_bytes}) with inuse_* from correlating alloc events against later free events inside the same window. Stack keys are the (chunkname, line) chain from symtab events. 3. Encode via lib/protobuf/encoder.lua + lib/pprof/defs.lua — schema already supports multi-sample-type profiles, declare four sample_type entries. 4. New endpoint /debug/pprof/heap?seconds=N on the JSON gateway. Same shape as /debug/pprof/profile (600 s cap, 503 on memprof-unavailable). Existing /debug/memprof stays for raw-trace use cases. | Known frictions: - misc.memprof.available == false on Apple Silicon (same arm64 constraint as the JIT — see reference_apple_silicon_no_jit). start() returns true but stop() says "profiler is disabled" and writes nothing. /debug/memprof already detects this and 503s; pprof-heap should do the same. Linux/x86_64 unaffected. - inuse_* is "alive at end-of-window", not "alive right now" — long-lived objects allocated before the window started never appear. Document this; Go heap profile has the same caveat. - Writing the binary parser without ground-truth output is the main risk — develop on a Linux box where memprof actually fires, validate against tools/memprof.lua textual report. | 1. /debug/pprof/heap?seconds=N returns valid pprof-shaped protobuf, parseable by `go tool pprof`. 2. On Apple Silicon, returns 503 with clear "memprof unavailable on arm64" message. 3. Round-trip tests in test/pprof_test.lua (same shape as the cpu profile tests). | Source: docs/TODO.md "Open / Pprof-shape /debug/pprof/heap". Referenced from app/etcd/debug.lua:16, lib/pprof/memprof.lua:12. | open | 3 | feature | NULL | NULL | 2026-05-19T13:34:30Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T13:34:30Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||
| tarantool-etcd-jg3 | a13319c39a4bdd813b6d85a5f391773719f4b5f9a43692850e00e8bb4928a25c | Replica route: config block + role plumbing | Add the role config surface for replica mode and validate/apply it. New block under app.roles.etcd, e.g.: replica: enabled: false mode: mirror # mirror (read-only) | proxy (forward writes) upstream_endpoints: ['http://etcd-a:2379', ...] username: '' # optional auth to upstream password: '' tls: {...} Wire validate/apply/stop in app/roles/etcd.lua: when replica.enabled, the local store must refuse normal write registration and instead start the sync fiber (other child issues). Validate that mode is one of mirror|proxy and endpoints is non-empty. No sync logic here — just config parsing, validation, and the on/off switch the other phases hang off of. | Mirrors the existing grpc/json/cmux config block validation in app/roles/etcd.lua. | open | 2 | task | NULL | NULL | 2026-05-20T06:17:54Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-kbc | 3b334f8edc7b7d1335eb359e0d4f364dd8acf1cbb760567eb695a1b7e940b54f | Conformance test: gRPC Watch on a follower replica | tests/conformance/replicaset_smoke_test.go covers ReadReplicatesToFollowers (Range on each follower after a leader Put) but nothing exercises a Watch stream *pinned to a follower endpoint* while mutations happen on the leader. The Lua integration test (test/grpc_integration_test.lua:547) explicitly punts: "True replicaset behaviors (watch deliveries across nodes ...) need a real Raft cluster and live in the Go harness." Watch on a follower has its own moving parts that Range does not: - the watcher fiber lives on the follower - kv_history rows arrive via replication (relay → applier), not via the local mutation - the box.on_commit broadcast must fire on the applier path (see memory feedback_tarantool_trigger_broadcast — broadcast from on_commit, not on_replace, so the woken reader sees committed state on the follower side too) Without this test, a regression in the follower-side watch wake-up would slip through the rs3 suite. | - Reuse mustDial(t, []string{followerEndpoint}) from existing rs3 tests — same dial pattern as ReadReplicatesToFollowers. - Use a short context.WithTimeout (5 s wall, 2 s wait-for-event) — replication lag on the local rs3 harness is sub-ms. - Use harness.UniqueKey(t) for key isolation. - Skip on non-rs3 backend (the single-node tarantool backend has no follower). - Mirror the synchronous "wait for created chunk" pattern jsonclient/watch already uses, even on the gRPC client — avoids the race where the Put commits before the Watch is registered. | 1. New test in tests/conformance/replicaset_smoke_test.go that: a. Spawns the rs3 backend, identifies leader + followers via rs.LeaderEndpoint / rs.Endpoints. b. Opens a Watch stream pinned to each follower endpoint (one subtest per follower). c. Issues a Put on the leader. d. Asserts the follower-side watcher receives the PUT event within a short deadline (≤2 s on a quiet box). e. Asserts the event header.revision matches the leader-side Put response revision. 2. Additional subtest: range watch ("/rs_smoke/watch/", "\0") on a follower receives multiple events in revision order when the leader issues several Puts. 3. Optional subtest: prev_kv populated correctly on the follower-side event when WithPrevKV is requested. 4. Suite stays green with CONFORMANCE_BACKEND=tarantool_rs3 go test -count=1 -run TestReplicasetSmoke -v. | Source: gap surfaced while porting docs/TODO.md to bd on 2026-05-19. Cross-refs: tests/conformance/replicaset_smoke_test.go ReadReplicatesToFollowers (line ~160), test/grpc_integration_test.lua:547 comment about which behaviors live where, memory feedback_tarantool_trigger_broadcast. | open | 2 | task | NULL | NULL | 2026-05-19T14:11:02Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:11:02Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||
| tarantool-etcd-lac | 9b0811dbe3090da92e2f2c059b263cbef43e1721b4418917747dcf3102a20f60 | Phase 5e — Lease option coverage | Per-option density on Lease RPCs. Canonical paths are already covered; what is missing is option coverage in the {tarantool, etcd} × {grpc, json} matrix. Smallest remaining surface — should be the warm-up before Phase 5f. Likely tests: - TestLeaseGrantWithExplicitID - TestLeaseGrantTTLBoundaries (TTL=0 / negative / very-large) - TestLeaseTimeToLiveAttachedKeys - TestLeaseRevokeRevokesAttachedKeys (each attached key disappears + watcher sees DELETE at the revoke revision) - TestLeaseKeepAliveOnceTTLZero (cross-wire — jsonclient-internal case already pinned) Sub-phases 5a-c each surfaced one Lua-side divergence — expect at least one more here. | Each listed test ported, runs on all four cells, passes (or is documented as a known gap in tests/conformance/harness/gaps.go cross-referenced from docs/TODO.md). | Source: docs/TODO.md "Open / Conformance matrix — Phase 5 option coverage". | open | 2 | task | NULL | NULL | 2026-05-19T13:34:01Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-lko | a9f5b3fdb1d8c955ea9817c5961cd2fd334733f9495cfcea8dc728d5d59c5bad | Route writes to current master (write-forwarding on followers) | Followers currently reject writes with ER_READONLY → gRPC UNAVAILABLE, and clientv3 does NOT fail over endpoints on Unavailable (see memory feedback_clientv3_error_assertions). Clients must pin to the leader, which breaks endpoint-agnostic client setups (AutoSyncInterval, DNS round-robin, k8s Service). Implement write-forwarding inside the role: when a follower receives a mutating RPC (Put / DeleteRange / Txn-with-writes / LeaseGrant / LeaseRevoke / LeaseKeepAlive / Compact / Auth* / Lock / Campaign / Resign / Proclaim), proxy it to the current Raft leader via experimental.connpool + a setuid stored Lua function (same pattern as MaintenanceMoveLeader, see project_cross_node_promote memory). Reads stay local per replicaset.read_pref (already implemented). | - Reuse the connpool helper introduced for MaintenanceMoveLeader (tests/conformance/harness/tarantool_rs_server.go:475 area). - Trigger forwarding inside grpc.lua make_handler before dispatching the write — cheaper than wrapping every kv/lease/txn module. - box.info.election.leader gives the leader id; map id→advertise URL via advertise.lua (already used for MemberList clientURLs). - Streaming RPCs (Watch, LeaseKeepAlive, Election Observe) are subtler — defer or handle separately; first cut should be unary-only. | 1. Mutating RPC on a follower in tarantool_rs3 backend succeeds (matches the leader-equivalent response shape, including header.revision monotonicity). 2. No regression in existing rs3 conformance subtests. 3. New conformance subtest TestWriteForwardingOnFollower covers Put/Txn/LeaseGrant from a follower endpoint. 4. If the leader is unknown (election in progress), return ErrGRPCNoLeader as today. | Discussed in chat 2026-05-19 as the only multi-master option that preserves etcd contract. Memory refs: project_cross_node_promote, feedback_clientv3_error_assertions. | open | 2 | feature | NULL | NULL | 2026-05-19T13:33:55Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T13:33:55Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||
| tarantool-etcd-m0w | 1e497e0d597a35ddd55d2b06dbb53bee3d2af9ede56d5397f2267151a481b309 | iproto-verify: etcd_unlock vs Lock.Unlock | Add Lua testkit verification for etcd_unlock (mirrors gRPC Lock.Unlock). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/lock. Call shape: local resp = etcd_unlock(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:18Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:18Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-m1n | c9126753270e756137235fe87d06b79c038f9607c12502bc9e772f6f2ff6cf6c | iproto-impl: etcd_election_leader vs Election.Leader | Wrap the existing handler election.leader (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Leader) as a Lua global etcd_election_leader callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_leader', wrap('election', 'leader')) under the appropriate service block; append 'etcd_election_leader' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Election.Leader returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_election_leader is callable from net.box:call('etcd_election_leader', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/election.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:48Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-mo5 | dbe7e65616d159fdbd81f97f8b988209daa63549799f00a9436da023cecace05 | iproto-verify: etcd_member_list vs Cluster.MemberList | Add Lua testkit verification for etcd_member_list (mirrors gRPC etcdserverpb.Cluster.MemberList). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/cluster. | Epic tarantool-etcd-w8q. Blocked on the matching impl issue. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:26Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-nbs | d8c32e3fb95d9e7bc7827a04bdbe8af747dd5df724c8d1b56f20654f307d2157 | TLS support on gRPC + JSON wires | Roadmap P0 blocker. etcd clients expect TLS on the client port (and the JSON/HTTP gateway). Implement TLS termination for both the gRPC/HTTP-2 (nghttp2) listener and the JSON-over-HTTP/1.1 gateway, including cmux'd single-port mode. Scope: server cert/key config, optional client-cert auth (--client-cert-auth equivalent), wiring through the role config (grpc.tls / json.tls blocks). | Roadmap-only item; no TLS issue existed in beads. | open | 0 | feature | NULL | NULL | 2026-05-20T06:55:22Z | Eugene Blikh | bigbes@gmail.com | 2026-05-20T06:55:22Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-ns0 | 20b6fc12f33291102415f4213204ede198952347fae1b7e670b587ba2f267a73 | iproto-verify: etcd_maintenance_defragment vs Maintenance.Defragment | Add Lua testkit verification for etcd_maintenance_defragment (mirrors gRPC etcdserverpb.Maintenance.Defragment). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/maintenance. | Epic tarantool-etcd-w8q. Blocked on the matching impl issue. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:35Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-nwl | 3f54509527d06071750dbdddfdcafe415133385b9549ce08b80b06cc16f9d6cf | iproto-verify: etcd_user_revoke_role vs Auth.UserRevokeRole | Add Lua testkit verification for etcd_user_revoke_role (mirrors gRPC Auth.UserRevokeRole). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_user_revoke_role(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:11Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:11Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-ovo | b02eee9877621d78af7f66286e7ff63fc6564aac6beeca0cb795fe667217cb17 | Learner: durable applied_index (WAL-equivalent for restart) | Persist enough raft state (currentTerm/HardState, applied_index, ConfState) so a restart resumes from the last applied entry instead of replaying from zero or forcing a full snapshot. Store in a dedicated space (e.g. etcd_raft_meta) written in the same transaction as each applied entry. On boot in learner mode: read last applied_index, reconnect transport, and request entries after it (or a snapshot if the leader has compacted past it). Tarantool's own WAL gives us durability of the *space writes*; this issue is specifically the raft bookkeeping that lets us re-attach to the cluster correctly. | etcd stores this as raft WAL + snapshot metadata; we collapse it to a meta space since Tarantool's WAL already durably persists the applied data. | open | 2 | task | NULL | NULL | 2026-05-20T06:45:17Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-ovt | db6cf24009cca490a9e5a89f705f27d73388ddfcc3513448452e373522faeeb5 | iproto-verify: etcd_member_remove vs Cluster.MemberRemove | Add Lua testkit verification for etcd_member_remove (mirrors gRPC etcdserverpb.Cluster.MemberRemove). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/cluster. | Epic tarantool-etcd-w8q. Blocked on the matching impl issue. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:21Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-ozm | 88152e03bc9011e822aa42ffc9212e11e04a9788bd5d40d5312f3e47da59657c | iproto-verify: etcd_user_list vs Auth.UserList | Add Lua testkit verification for etcd_user_list (mirrors gRPC Auth.UserList). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_user_list(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:09Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:09Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-p3s | d7ab326ea50217052ff7528067d9bda449d1d177009210c5b6dc67df52f33a52 | iproto-verify: etcd_election_leader vs Election.Leader | Add Lua testkit verification for etcd_election_leader (mirrors gRPC v3electionpb.Election.Leader). Same test pattern as verify-only tasks: positive path plus at least one error path, response shape matches gRPC, error codes from app/etcd/errors.lua. For UNIMPLEMENTED-by-design endpoints (Cluster.MemberAdd/Remove/Update/Promote), assert the wrapper returns the canonical UNIMPLEMENTED error consistent with gRPC rather than skipping. Goes in test/iproto_parity_test.lua under group iproto/parity/election. | Epic tarantool-etcd-w8q. Blocked on the matching impl issue. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:48Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-q5f | 722c317df5aebe05f32f99bf226d4b916604f1518089bea768b2ed206866ecd3 | Learner: snapshot receive (bbolt parse + bucket translation) | Handle /raft/snapshot. When we fall too far behind (or on first join), the leader ships a bbolt DB file dump, NOT raft entries. Two options: (a) parse the bbolt file and translate etcd's buckets — key (the mvcc keyspace), meta (consistent_index, scheduledCompactRev, finishedCompactRev), lease, auth/authUsers/authRoles, members/members_removed, cluster, alarm — into our etcd_* spaces; or (b) refuse snapshots and bootstrap via clientv3 Range/Watch instead, accepting that the cluster MAY force a snapshot mid-stream if we lag past its compaction window (it eventually will). Recommend (a) for a true learner. Needs a minimal bbolt page/leaf reader in Lua or via FFI. This is the phase most likely to surprise — it bypasses the raft proto entirely. | bbolt format: page-based B+tree, freelist, meta pages with txid. Bucket values for mvcc keys are mvccpb.KeyValue protobufs keyed by revision{main,sub}. This is the single biggest sub-effort in the epic. | open | 2 | task | NULL | NULL | 2026-05-20T06:45:16Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-rzh | 26beb784e16ef7c22030f27a08fe4e55b5e0453b6cd19af9df1ffd97a8bb3235 | iproto-impl: etcd_maintenance_status vs Maintenance.Status | Wrap the existing handler maintenance.status (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.Status) as a Lua global etcd_maintenance_status callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_status', wrap('maintenance', 'status')) under the appropriate service block; append 'etcd_maintenance_status' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Maintenance.Status returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_maintenance_status is callable from net.box:call('etcd_maintenance_status', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/maintenance.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:32Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-rzr | 3973dcbaf27d8ffaf25bdad2afcfcbfeb9e6deb07cd8ecf62c5a6446247c3468 | nghttp2 unary send-path rewrite — close parallel KVGet gap, drop jit.off | Parallel KVGet on tarantool is ~70% slower than etcd at GOMAXPROCS=6 (12 688 ops/s vs 21 900 ops/s; p95 970 µs vs 405 µs — docs/BENCH.md "Linux x86_64 — KVGet matrix, 2026-05-15"). Root cause: per-Connection IO mutex in lib/nghttp2/grpc.lua (Connection:_locked) — nghttp2 sessions are not reentrant, so every fiber's submit_response + send_all + sock:write serializes. Etcd has no such constraint. Fix: pre-build HEADERS + DATA + trailers in pure Lua, skip nghttp2's C→Lua data-source callback on the unary send path, recover ~10–20% throughput lost to jit.off + drop the JIT pin entirely. | See memory project_nghttp2_send_callback_rewrite for the plan. Pre-frame DATA in Lua, avoid re-entering nghttp2 mid-send. Touch points: - lib/nghttp2/grpc.lua (Connection, _locked, send_response) - lib/nghttp2/ffi.lua (data-source callback signature) - M.recv/M.send/M.send_all/M.send_data currently pinned jit.off — un-pin once the callback re-entry is gone (memory feedback_nghttp2_session_not_reentrant explains the original panic). | 1. BenchmarkKVGetParallel/point closes the gap to within ~10% of etcd at GOMAXPROCS=6. 2. p95 latency under parallel load drops below 600 µs. 3. No bad-callback panics across 10 verbose runs (the regression test from commit d0fa396). 4. jit.off removed from M.recv/M.send/M.send_all/M.send_data. | Sources: docs/BENCH.md "Linux x86_64" + memory notes project_nghttp2_send_callback_rewrite, feedback_nghttp2_session_not_reentrant, feedback_nghttp2_dual_connection. | open | 2 | task | NULL | NULL | 2026-05-19T13:34:42Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T13:34:42Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||
| tarantool-etcd-rzs | 63c2e0e3f3c883b2db5734e851457a1f568e3a1ebb871de515f13411bd7ecbd9 | iproto-impl: etcd_member_update vs Cluster.MemberUpdate | Wrap the existing handler cluster.member_update (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Cluster.MemberUpdate) as a Lua global etcd_member_update callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_member_update', wrap('cluster', 'member_update')) under the appropriate service block; append 'etcd_member_update' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Cluster.MemberUpdate returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_member_update is callable from net.box:call('etcd_member_update', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/cluster.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:23Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-sdt | ce9fb24507b45a493bd9ffc4a4ab22edafe46b9e41a95b2813bb6b2016b0ccc8 | iproto-verify: etcd_auth_status vs Auth.AuthStatus | Add Lua testkit verification for etcd_auth_status (mirrors gRPC Auth.AuthStatus). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/auth. Call shape: local resp = etcd_auth_status(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:04Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:04Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-sqv | e03dd24141b120acf0cc989ed396918ed61284c9962f1c036f30a262a51d39e6 | iproto-impl: etcd_election_proclaim vs Election.Proclaim | Wrap the existing handler election.proclaim (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Proclaim) as a Lua global etcd_election_proclaim callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_proclaim', wrap('election', 'proclaim')) under the appropriate service block; append 'etcd_election_proclaim' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Election.Proclaim returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_election_proclaim is callable from net.box:call('etcd_election_proclaim', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/election.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:46Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-sy6 | ff088cd8c36175c942b8e80aa7a1bfa3bdaa64bf92a9ff46f8c736505ea0b302 | iproto-verify: etcd_watch_pull vs Watch.Watch-pull | Add Lua testkit verification for etcd_watch_pull (mirrors gRPC Watch.Watch-pull). Successful path: assert response shape matches the gRPC response message after MsgPack round-trip. Error path: at least one error case asserting {code, message} matches app/etcd/errors.lua catalog. Exercise at least one non-default option if applicable. Goes in test/iproto_parity_test.lua under group iproto/parity/watch. Call shape: local resp = etcd_watch_pull(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:53:57Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:53:57Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-tf0 | 4410402a2773378d989b3453c6d566e9ab0eb85ec6a8ba9eb21801b478e96d73 | iproto-impl: etcd_maintenance_hash_kv vs Maintenance.HashKV | Wrap the existing handler maintenance.hash_kv (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.HashKV) as a Lua global etcd_maintenance_hash_kv callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_hash_kv', wrap('maintenance', 'hash_kv')) under the appropriate service block; append 'etcd_maintenance_hash_kv' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Maintenance.HashKV returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83. | etcd_maintenance_hash_kv is callable from net.box:call('etcd_maintenance_hash_kv', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply. | Epic tarantool-etcd-w8q. Handler at app/etcd/maintenance.lua. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:39Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-tt6 | 63510fbc9abb4568f1a181ec6515e1edededff7dbb3a0cf8e1f67e62b24c780d | Replica route: lease / auth state mirroring (scope v1 vs later) | KV is the v1 target; this issue scopes how non-KV state behaves in replica mode and what (if anything) v1 mirrors. Questions: - Leases: do we mirror upstream lease grants/TTLs/expiry so locally-served keys show correct lease attachment, or pass-through lease ops to upstream? At minimum the lease_id on replicated kvs must round-trip; full lease lifecycle mirroring may be later. - Auth: mirror upstream users/roles/permissions, or run replica reads unauthenticated/locally-authed? Decide whether auth is enforced on the replica or delegated. - Watch served to local clients: our Watch subsystem already reconstructs from kv_history, which the tail populates — confirm local watchers work transparently once KV sync lands. Output: a documented v1 scope (likely 'KV + lease_id round-trip only; auth+full-lease+ deferred') appended to docs/TODO.md, plus any follow-up issues. | Likely mostly a scoping/decision issue that spawns concrete follow-ups; keep v1 KV-only. | open | 2 | task | NULL | NULL | 2026-05-20T06:17:57Z | Eugene Blikh | bigbes@gmail.com | 2026-05-20T06:17:57Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-uee | 9e6ca4342149c79eee16a063f881ae3eb1683b9de5774eae58d2b37bfc8bcb9b | Replica route: bootstrap snapshot import | On entering replica mode, pull the full upstream keyspace once and load it into our etcd_* spaces, recording the upstream revision the snapshot was taken at (the Watch tail starts from here). Approach: a clientv3-style Range over the whole keyspace ([\\x00, \\x00) with WithRange/WithFromKey) reading at a single revision (use the header.revision from the first Range, or RangeRequest with revision pinned + paging via WithLimit + WithMinModRev/last-key continuation). Persist each kv with its create_revision/mod_revision/version/lease intact. Alternatively consume Maintenance.Snapshot if/when interop lands (tarantool-etcd-16d) — but Range is the dependency-free path for v1. Output: etcd_* spaces populated, and the 'synced through revision R' watermark persisted for the tail phase to resume from. | Must preserve upstream create_revision/mod_revision/version exactly — feeds revision-alignment. Page large keyspaces to avoid one giant Range. | open | 2 | task | NULL | NULL | 2026-05-20T06:17:54Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:37Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||||
| tarantool-etcd-umc | d8474c3796303d77baae0a958775f27a81b09ad2e0afaa4a00084cdf0ab6b7e9 | Learner: config block + role plumbing | Add the role config surface for learner mode and wire validate/apply/stop in app/roles/etcd.lua. New block under app.roles.etcd: learner: enabled: false cluster_peers: ['http://etcd-a:2380', ...] # PEER (2380) URLs, not client (2379) advertise_peer_url: 'http://this-node:2380' # how the cluster reaches us peer_tls: {...} Validate: when learner.enabled, the local store refuses normal client write registration; cluster_peers + advertise_peer_url non-empty; peer URLs are well-formed. No raft/transport logic here — just config parsing, validation, and the on/off switch the other phases hang off. Mirrors the existing grpc/json/cmux config validation in app/roles/etcd.lua. | Distinct from the watch-mirror config (tarantool-etcd-jg3): peer (2380) URLs not client (2379), advertise_peer_url required for the cluster to dial us back. | open | 2 | task | NULL | NULL | 2026-05-20T06:45:13Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-unw | f79d825d667d7493d1fbad53e65026978cea04ebcf650b8c77456f87f7698c30 | Tarantool metrics integration | Roadmap P0 blocker. Expose etcd-server operational metrics through Tarantool's metrics subsystem (request counts/latencies per RPC, watch/lease counts, revision, compaction, store size). Should surface via the standard Tarantool metrics collectors so existing TT monitoring (Prometheus exporter) picks them up. Consider parity with etcd's own /metrics names where it aids dashboards. | Roadmap-only item; no metrics issue existed in beads. | open | 0 | feature | NULL | NULL | 2026-05-20T06:55:23Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T14:27:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 |