jklbeip6gas912an6npi108c7jadlrud · 117 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-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-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-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-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-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 | |||||||||||||||||||||||
| 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-sir | 5cc0da191ba98b3f835cc3fcdc3e3f5ed44926cb471cb6df204b16f644957871 | JWT auth-token mode (--auth-token=jwt) — we only have simple tokens | etcd supports two auth-token modes: simple (an opaque token in a server-side table) and jwt (a signed, self-contained token the server verifies with a key, no server-side session state). etcd 3.7 leans further on JWT — 'clients may now set the JWT directly, offering more flexibility in authentication options.' We implement simple-token only: Auth.Authenticate mints an opaque token stored in the etcd_tokens space (truncated on auth disable, app/etcd/auth.lua). There is no JWT handling anywhere in app/etcd/. A client configured against a JWT-mode etcd, or one presenting a pre-issued JWT, gets rejected by us. This also matters for our own topology: simple tokens are server-local session state, so under a replicaset a token minted on one node is not honored by another unless etcd_tokens replicates and stays consistent. JWT is stateless and sidesteps that entirely. Scope: an auth.token config block selecting simple|jwt, JWT sign/verify (RS256 + HS256 at minimum) over the etcd claim set (username, revision), key material from config, and acceptance of a client-supplied JWT on both wires. | Needs a JWT implementation in Lua — check what Tarantool ships (digest for HMAC/SHA, crypto for RSA) before pulling a dependency. Note digest.base64_encode MIME-wraps at 76 chars by default; JWT needs {nowrap = true} and URL-safe alphabet. | Server boots in jwt mode; a token minted by Authenticate verifies on a different replicaset node without shared session state; a conformance cell runs the auth suite in jwt mode against both backends; simple mode stays the default and unchanged. | open | 2 | feature | NULL | NULL | 2026-07-17T11:30:45Z | Eugene Blikh | bigbes@gmail.com | 2026-07-17T11:30:45Z | 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 |