93u4016bdp640rehgng7dhmbv1jkpv9q · 133 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-9lj | 5af1aed464b7f2a3ca9975c39b49b91ae39658007b617e3bee18ab295d71a074 | iproto-verify: etcd_user_delete vs Auth.UserDelete | Add Lua testkit verification for etcd_user_delete (mirrors gRPC Auth.UserDelete). 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_delete(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:07Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:07Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-9z2 | f38d22b50cefe3aad567bf495f853ea9e6c187bef2586c7ed1fc8f540cd6bb29 | Phase 5f — Watch option coverage | Per-option density on Watch RPCs. Big stream-shaped surface, highest remaining value but also highest effort. Run after Phase 5e. Likely tests: - TestWatchWithFilterPut / TestWatchWithFilterDelete (server-side event filtering) - TestWatchProgressNotifyExplicit (RequestProgress on demand vs the implicit 10-minute heartbeat already covered) - TestWatchWithFragment (large-response fragmentation — may surface a tarantool-side gap) - TestWatchWithPrevKV (per-watcher prev-kv flag, distinct from WithPrevKV on Put/Delete) - TestWatchFromCompactedRevision (ErrCompacted returned on the stream, not as a typed gRPC status) | Each listed test ported, runs on all four cells, passes (or documented as a known gap with cross-reference). | Source: docs/TODO.md "Open / Conformance matrix — Phase 5 option coverage". Priority note (TestWatchWithPrevKV): Tarantool EE uses etcd as a centralized-config backend (config.storage / etcd config source in TT 3.x). On boot it reads config from etcd and opens a Watch with prev_kv set to diff old-vs-new config on live reload. So Watch prev_kv is exercised by a first-class ecosystem consumer, not just the conformance suite — it should be treated as the highest-value test in this group for drop-in TT EE compatibility. Implementation already exists (feature built, conformance assertion missing): - app/etcd/watch.lua:83 lookup_prev_kv() walks kv_history backwards (LT on mod_revision) for the prior non-tombstone value - app/etcd/watch.lua:268 stores per-watcher flag; propagated via grpc.lua:358, json.lua:205, server.lua:185 - auth.lua:317 requires READ perm when prev_kv requested Remaining work for prev_kv is the TestWatchWithPrevKV conformance case against real etcd 3.6, not the Lua implementation. | open | 2 | task | NULL | NULL | 2026-05-19T13:34:06Z | 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-a4v | 3156d399bad09c4b450e5716bdbf261abc162ade6d53632d4feb2288ccee49a3 | iproto-verify: etcd_auth_enable vs Auth.AuthEnable | Add Lua testkit verification for etcd_auth_enable (mirrors gRPC Auth.AuthEnable). 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_enable(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:03Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:03Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-acp | 97d1c50f3eb3e7ccc1e25dc0461f3f769efd5ef59f4e35f50d7995d0ad317a45 | iproto-verify: etcd_range vs KV.Range | Add Lua testkit verification for etcd_range (mirrors gRPC KV.Range). 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_range(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:53:52Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:53:52Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-ag2 | 626fad0022546f7a8fa1aa3ad95681ae236ec2219d5303dec173c668a8c7fd31 | iproto-verify: etcd_user_add vs Auth.UserAdd | Add Lua testkit verification for etcd_user_add (mirrors gRPC Auth.UserAdd). 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_add(req). | Verification-only. Wrapper exists at app/etcd/api.lua. Epic tarantool-etcd-w8q. | open | 3 | task | NULL | NULL | 2026-05-19T14:54:06Z | Eugene Blikh | bigbes@gmail.com | 2026-05-19T14:54:06Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-agm | d4a2da2e9308e8a545805d7d930766b363bf014718142b5c35c99cc49a8e1940 | Negative Watch start_revision replays entire history instead of cancelling | etcd (server/etcdserver/api/v3rpc/watch.go): StartRevision < 0 gets an immediate Created+Canceled response with WatchId=-1 and CancelReason=ErrCompacted; the watcher is never registered. We only special-case nil/0 (app/etcd/watch.lua:268-284). A start_revision of -1 falls through to 'start_rev = start_rev - 1', and the compaction guard at :279 is gated on '> 0' so it skips the check entirely — the watcher registers with last_seen_revision = -2 and events_since (watch.lua:135,141-142) scans kv_history GE from -1, replaying all retained history. Neither wire validates (grpc.lua:424, json.lua:200). Impact: a client passing WithRev(-1) gets a full-history flood instead of a cancel. | start_revision < 0 returns created+canceled with cancel_reason set and registers no watcher, on both wires; a test pins -1 specifically. | open | 1 | bug | NULL | NULL | 2026-07-17T13:19:08Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T13:19:08Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| tarantool-etcd-ak9 | a72aa034b84133ebc9e1d6502a314663ac057b4ed21dff77cd622473e65cd53f | iproto-verify: etcd_auth_disable vs Auth.AuthDisable | Add Lua testkit verification for etcd_auth_disable (mirrors gRPC Auth.AuthDisable). 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_disable(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-amf | 291d4ae16a4b9432925311b49c11ba8000cce715301d29e6bdff95860fbdd176 | RoleGrantPermission accepts unsatisfiable ranges (empty key or key >= range_end) | etcd's isValidPermissionRange returns ErrInvalidAuthMgmt for an empty key or key >= range_end (auth/store.go). app/etcd/auth.lua:653-671 stores perm.key/range_end verbatim; the invalid permission is then silently stored and never matches anything — the admin believes a grant exists that cannot fire. Silent-misconfiguration class. Everything else in this area is correct (nil-perm rejection, revoke semantics, bytes/base64 typing). errors.invalid_auth_management() already exists, so this is a small fix. | Empty key or key >= range_end rejected at grant time with the etcd error; existing valid grants unaffected; test pins both invalid shapes. | open | 3 | bug | NULL | NULL | 2026-07-17T13:20:52Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T13:20:52Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| 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-dh3 | 6a957612b50e5ee613585d98d570b2f43fa00a9265a5dad4d58971140cd39cb2 | Watch header.revision can go backwards on a stream (progress vs event fiber interleave) | etcd 3.4.22/3.5.5 fixed this by routing progress through the stream's single sendLoop. Our RequestProgress computes a header, then performs yielding per-watcher writes (app/etcd/grpc.lua:527-533); a concurrent event fiber (grpc.lua:304,338) can interleave a newer-revision response first, so the client observes header.revision going backwards — which clients treat as a hard invariant violation. Race-shaped: argued from fiber structure, not observed. Reproducer first. Likely shares a root cause with the WatchProgressRequest synchronisation issue — consider fixing together via a single per-stream writer fiber. | header.revision is monotonic per stream under concurrent progress+event load; stress reproducer exists. | open | 2 | bug | NULL | NULL | 2026-07-17T13:20:16Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T13:20:16Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| 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-e3d | 6ab01fc66074fb8cbaf998a242421bed2c095548c511728dcfc4fadf5803c22f | [security] Txn nested Put ignores prev_kv READ check — RBAC bypass leaks values to WRITE-only grants | A user granted WRITE-only on a key can read its value via Txn{success=[Put(key, prev_kv=true)]}. Verified by hand: - app/etcd/auth.lua:313-314 — the nested-op permission walk does only 'M.require_permission(PERM_WRITE, op.request_put.key)' for request_put. No prev_kv READ check. - The asymmetry proves it is an oversight, not a decision: the ADJACENT branch for request_delete_range (auth.lua:316-320) DOES check 'if r.prev_kv then require_permission(PERM_READ, ...)', and the top-level kv.M.put (app/etcd/kv.lua:561-563) does the same. - The leak is client-observable: execution dispatches to put_internal, which populates the response — app/etcd/kv.lua:538-540 'if req.prev_kv and prev_kv then resp.prev_kv = prev_kv end'. etcd runs full checkPutAuth on txn puts (server/etcdserver/apply/auth.go) — WRITE plus READ when prev_kv/ignore_value/ignore_lease is set. Same bug class upstream fixed as CVE-2026-33413 / CVE-2026-33343. Second, separable defect in the same area: checkLeasePuts has no analogue anywhere. etcd denies attaching a lease when the caller cannot write the OTHER keys already on that lease; we only re-check on the revoke side (app/etcd/lease.lua:143). Neither the top-level nor the nested Put path sweeps the lease's key set. | Factor a single check_put_auth(key, prev_kv, lease) used by BOTH kv.M.put and auth.check_txn_ops so the two paths cannot drift again — the drift is what caused this. The lease-attach sweep is separable; split it out if it grows. | A WRITE-only user gets PermissionDenied for Txn{Put(prev_kv=true)} on both wires; the equivalent top-level Put still behaves as today; a Lua test in test/auth_test.lua pins the nested case specifically; lease-attach denial covered or split to its own issue. | open | 0 | bug | NULL | NULL | 2026-07-17T13:18:42Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T13:18:42Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| tarantool-etcd-fv9 | 831466004ea8e32443ae2880646ec03b2fe3e529023e793ebbb93b3622b84f99 | gRPC connections closed after 30s idle; no server keepalive PINGs | lib/nghttp2/grpc.lua:394-398 hardcodes 'local readable = self.sock:readable(30)' and breaks the read loop when it returns false — the comment reads 'Idle timeout — close the connection.' So any gRPC connection with no INBOUND bytes for 30s is dropped. etcd does the opposite: --grpc-keepalive-interval (default 2h) PINGs idle connections to keep them alive. Supporting evidence: lib/nghttp2/session.lua:611-620 defines submit_ping with zero callers; ENHANCE_YOUR_CALM (lib/nghttp2/ffi.lua:892) is declared and never used; no keepalive knob exists in app/roles/etcd.lua. IMPACT NOTE (deliberately downgraded from the sweep's 'client-breaking'): clientv3 auto-reconnects and resumes watches from the last revision, so the real cost is reconnect churn, dropped idle streams, and latency spikes — not breakage. An idle Tarantool EE config.etcd watch would bounce every 30s. Worth fixing; not an outage. The conformance suite cannot see this: no test idles for 30s. | Cheapest correct fix is to stop treating 'no inbound bytes' as death — loop on readable() rather than breaking, and only close on EOF/error. Optionally send a PING on idle and expose grpc.keepalive.{interval,timeout} in roles_cfg. Consider whether any deployment relies on the 30s reap to shed dead sockets before removing it outright. | A connection idle >30s stays open and serves the next request; an idle Watch keeps delivering after 60s+; keepalive interval/timeout configurable; a test covers the idle case. | open | 2 | bug | NULL | NULL | 2026-07-17T13:19:34Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T13:19:34Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | <binary> | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| 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. | etcd 3.7 metric surface additions (from the 3.7.0 announcement) — fold into the name/label diff, and note that the diff must be taken against a 3.7 scrape once tarantool-etcd-cc7 bumps the conformance backend off 3.6: - etcd_server_request_duration_seconds (new, non-debugging — likely dashboard-relevant) - etcd_debugging_server_watch_send_loop_watch_stream_duration_seconds - etcd_debugging_server_watch_send_loop_watch_stream_duration_per_event_seconds - etcd_debugging_server_watch_send_loop_control_stream_duration_seconds - etcd_debugging_server_watch_send_loop_progress_duration_seconds The four watch send-loop series are etcd_debugging_* and describe upstream's internal watch send loop, which our watch.lua (fiber.cond + kv_history catch-up) has no structural analogue for — candidates for the 'stub or omit' bucket rather than the 'map' bucket. | open | 2 | feature | NULL | NULL | 2026-05-20T19:08:45Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T11:31:01Z | 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-hzu | 14fdd6958ceed40cb4c8fba54490d15898bbb96373552fcfcf59575bef43a86f | Watch on a future revision gets progress notifies below start_revision | etcd suppresses progress notifications for a watcher whose start_revision is ahead of the current revision — watchable_store.go:524, 'if rev < w.startRev { return false }' (PR #20286, 3.6). We emit the CURRENT header unconditionally on both the periodic path and ProgressRequest (app/etcd/grpc.lua:394-402, grpc.lua:522-533, app/etcd/json.lua:289-298). The wire layers do not even retain start_revision on the watcher handle, so the check cannot be made where the notify is sent. Impact: a client watching from a future revision sees header.revision values below the revision it asked to start at, which breaks the 'progress notify means I am caught up to here' contract. | A watcher created with start_revision > current gets no progress notify until the store reaches that revision; both wires; test pins it. | open | 2 | bug | NULL | NULL | 2026-07-17T13:20:14Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T13:20:14Z | 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-ipr | 7f0f2f7a10fe1e8c085396a71c2280cf000627d894f31b2e7d6307c2a53bf5bc | LeaseKeepAlive on a dead lease tears down the whole bidi stream (should send TTL=0) | etcd's v3rpc/lease.go sends LeaseKeepAliveResponse{TTL:0} for an unknown/expired lease and KEEPS THE STREAM OPEN. We close the stream with gRPC NOT_FOUND (app/etcd/grpc.lua:603-611); the JSON gateway emits an {"error":...} chunk instead of {"result":{"TTL":"0"}}. Impact: clientv3 multiplexes every lease's keep-alive onto ONE stream. One dead lease therefore tears down the shared stream for all live leases and causes retry churn until it ages out. This is deliberate (see the comment at app/etcd/lease.lua:203-210, a fiber-pinning concern) — but it is recorded ONLY in a code comment, which violates the project rule that a deliberate divergence goes in docs/TODO.md. That is also why the sweep initially read it as untracked. Either implement it or document it; the current state is the worst of both. | The fiber concern looks solvable without closing: drop the dead lease from the stream's keep-alive set, send the TTL=0 frame, and continue the recv loop. If it is kept as-is instead, add it to docs/TODO.md 'Deliberately not done' with the fiber rationale. | KeepAlive on an expired lease returns TTL=0 and the stream stays open on both wires; other leases on the same stream keep renewing; if closed as WONTFIX, docs/TODO.md carries the rationale. | open | 1 | bug | NULL | NULL | 2026-07-17T13:19:06Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T13:19:06Z | 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-mah | 9a466a5136be87beabd361f6098012ee8e2ee48bd3ccb1250ca93018108ada6f | Unix socket listener for gRPC + JSON (etcd 3.7) | etcd 3.7 adds Unix socket endpoints — local communication without a TCP port, aimed at development and edge devices. We bind TCP only: the role's grpc.listen / json.listen are host:port, and there is no unix path handling in app/roles/etcd.lua, app/etcd/grpc.lua, or lib/cmux.lua. For a Tarantool-embedded etcd this is more than parity: a co-located Tarantool EE instance reading its centralized config from us over a unix socket skips the loopback stack and needs no port allocated or firewalled. Scope: accept a unix:// (or unix/:) listen URI in the role config, bind an AF_UNIX socket, and confirm the cmux HTTP/2-preface peek and the PeekSock replay work unchanged over it (they should — cmux only needs a stream socket). | Tarantool's socket.tcp_server has a unix-socket sibling; confirm which API the nghttp2 server layer can accept a listening socket from. Decide the socket file lifecycle: stale-file removal on bind, permissions, and unlink on role stop. | Role boots with a unix listen path; grpc + JSON both serve over it; cmux multiplexes both on one unix socket; a conformance or Lua test dials it; socket file is cleaned up on stop. | open | 3 | feature | NULL | NULL | 2026-07-17T11:30:46Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T11:30:46Z | 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 |