~bigbes/tarantool-etcd · issues

ngc6e50aqta3qcfq33qjlcvj737k677p · 108 rows

idcontent_hashtitledescriptiondesignacceptance_criterianotesstatuspriorityissue_typeassigneeestimated_minutescreated_atcreated_byownerupdated_atclosed_atclosed_by_sessionexternal_refspec_idcompaction_levelcompacted_atcompacted_at_commitoriginal_sizesenderephemeralwisp_typepinnedis_templatemol_typework_typesource_systemmetadatasource_repoclose_reasonevent_kindactortargetpayloadawait_typeawait_idtimeout_nswaitershook_beadrole_beadagent_statelast_activityrole_typerigdue_atdefer_untilno_historystarted_at
tarantool-etcd-b08e3928051dd644ec2d3c70348320e479a23d4e425c4f5776f5a2cbbfc3d571607Phase 5g — Auth/Cluster/Maintenance/Lock/Election option coveragePer-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".open3taskNULLNULL2026-05-19T13:34:10ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:10ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-bdfbfc4038d48324b7c9fc5e533914f732797d0d1bb9a7f9d09560a51dc7cce0722gRPC server reflectionRoadmap 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.open1featureNULLNULL2026-05-20T06:55:23ZEugene Blikhbigbes@gmail.com2026-05-20T06:55:23ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-bg44f65298830b799a0aa90d2dadbcb7f92f52d144db8dc119673c85221d1f7ffbaiproto-verify: etcd_role_list vs Auth.RoleListAdd 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.open3taskNULLNULL2026-05-19T14:54:14ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:14ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-bol6e7729d0a88e476af22e1b9544083fc6358ea78739d3f4496e69e263f342d93fiproto-verify: etcd_role_add vs Auth.RoleAddAdd 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.open3taskNULLNULL2026-05-19T14:54:12ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:12ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-boq78f7ab0f980e3e418ac85b10e54290632eb565a339b43e58c52e1512d179539aLearner: 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.open2taskNULLNULL2026-05-20T06:45:15ZEugene Blikhbigbes@gmail.com2026-05-20T06:45:15ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-bq8384f622c395002fdc1fa6c43c9005f80116e1c4c08c9aed8828a8671b4293a6biproto-verify: etcd_lease_revoke vs Lease.LeaseRevokeAdd 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.open3taskNULLNULL2026-05-19T14:53:59ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:59ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-buq9370d11c13a9d704f0b6e3f0241d2513428257a7e3278aacfed07ddb5818c965Drop stale TODO-item-14 comment in app/etcd/json.luaapp/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.open4taskNULLNULL2026-05-19T13:34:52ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:52ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-cnjed489cb32430e8d6cd2ea3b91464291e41a9c603992a7c8baf680dd56c313931[epic] Raft-learner replica — join an etcd cluster as a non-voting memberAttach 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.open2featureNULLNULL2026-05-20T06:39:59ZEugene Blikhbigbes@gmail.com2026-05-20T06:39:59ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-cpp51598282012a458cd2be1c01fc8c7326fd8c8624f667d400c44e1d56412c5f5bC-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.open1featureNULLNULL2026-05-20T06:55:24ZEugene Blikhbigbes@gmail.com2026-05-20T06:55:24ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-cz54624dbf6ad6bf8e90df4dfb60839daf2c9b81d1490c3dccf619f343a0eef92fciproto-verify: etcd_maintenance_move_leader vs Maintenance.MoveLeaderAdd 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.open3taskNULLNULL2026-05-19T14:54:42ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:42ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-dkr36433e1a02770d7b48365cfd48bf7f0f3db1f7e2f287b723f41083bd7ff61377Alternative transports for gRPCRoadmap 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.open2featureNULLNULL2026-05-20T06:55:26ZEugene Blikhbigbes@gmail.com2026-05-20T06:55:26ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-dmtc018e2fea002b9ae10b51cd9b69a7fc6e4137e1abddda5894b9874aea50df95fiproto-verify: etcd_election_resign vs Election.ResignAdd 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.open3taskNULLNULL2026-05-19T14:54:53ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:53ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-g1a94cc76ee0c10feae7cdcc327b843bb2cd907d8b2e7190c64ce7f199385cb4caaiproto-impl: etcd_member_list vs Cluster.MemberListWrap 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.open3taskNULLNULL2026-05-19T14:54:25ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:25ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-gz4ce1604ad8990ae56710064076900a30bc028c5a592327c484f437c820d40360ciproto-verify: etcd_put vs KV.PutAdd 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.open3taskNULLNULL2026-05-19T14:53:53ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:53ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-h8r864b7efe5edb39f6670b5bb0ca34accb55dcf6beba77a46d7fd987280df09847iproto-verify: etcd_election_observe vs Election.ObserveAdd 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.open3taskNULLNULL2026-05-19T14:54:51ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:51ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-hcoa75a35cc4e55aca16758bcde37bde3575cc73d8106697aa8e8274c5013dfdb31iproto-impl: etcd_election_observe vs Election.ObserveWrap 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.open3taskNULLNULL2026-05-19T14:54:50ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:50ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-hlx629cacff048485b7bfdb7696ef646a8c092fc87f720e2f43caae3e2bfd8170aeReplica route: watch-tail live syncAfter 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).open2taskNULLNULL2026-05-20T06:17:55ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:55ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-huo96dcd8d31ebf9f5f56da997ac7d459e417b024ed5bd339a4a5c33c469b4e96c1etcd /metrics compatibility — match upstream Prometheus metric names + endpointExpose 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.open2featureNULLNULL2026-05-20T19:08:45ZEugene Blikhbigbes@gmail.com2026-05-20T19:08:45ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-hx983339a7afd9423290ef9d2cd3efe2cd40957688e945103b127b1b1bbb8e52b4aiproto-impl: etcd_member_remove vs Cluster.MemberRemoveWrap 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.open3taskNULLNULL2026-05-19T14:54:21ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:21ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-iij291c145ebcd3fb5899f03f83ed0a7ad011df3459d5a8ed30498483aef3cd726fiproto-verify: etcd_lock vs Lock.LockAdd 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.open3taskNULLNULL2026-05-19T14:54:17ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:17ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-iz4362238cde2d5629a32ed5166d55ec1085d0b4eb2cc0715b0eab59a0ab734967fiproto-verify: etcd_role_grant_permission vs Auth.RoleGrantPermissionAdd 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.open3taskNULLNULL2026-05-19T14:54:15ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:15ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-j1cd72af58dd67917cd0d6f45c09ebc8410746a5a5fa3ce0f2fc547a0845aa4d6da/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.open3featureNULLNULL2026-05-19T13:34:30ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:30ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-jg3a13319c39a4bdd813b6d85a5f391773719f4b5f9a43692850e00e8bb4928a25cReplica route: config block + role plumbingAdd 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.open2taskNULLNULL2026-05-20T06:17:54ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:54ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-kbc3b334f8edc7b7d1335eb359e0d4f364dd8acf1cbb760567eb695a1b7e940b54fConformance test: gRPC Watch on a follower replicatests/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.open2taskNULLNULL2026-05-19T14:11:02ZEugene Blikhbigbes@gmail.com2026-05-19T14:11:02ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-lac9b0811dbe3090da92e2f2c059b263cbef43e1721b4418917747dcf3102a20f60Phase 5e — Lease option coveragePer-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".open2taskNULLNULL2026-05-19T13:34:01ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:01ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-lkoa9f5b3fdb1d8c955ea9817c5961cd2fd334733f9495cfcea8dc728d5d59c5badRoute 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.open2featureNULLNULL2026-05-19T13:33:55ZEugene Blikhbigbes@gmail.com2026-05-19T13:33:55ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-m0w1e497e0d597a35ddd55d2b06dbb53bee3d2af9ede56d5397f2267151a481b309iproto-verify: etcd_unlock vs Lock.UnlockAdd 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.open3taskNULLNULL2026-05-19T14:54:18ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:18ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-m1nc9126753270e756137235fe87d06b79c038f9607c12502bc9e772f6f2ff6cf6ciproto-impl: etcd_election_leader vs Election.LeaderWrap 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.open3taskNULLNULL2026-05-19T14:54:48ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:48ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-mo5dbe7e65616d159fdbd81f97f8b988209daa63549799f00a9436da023cecace05iproto-verify: etcd_member_list vs Cluster.MemberListAdd 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.open3taskNULLNULL2026-05-19T14:54:26ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:26ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-nbsd8c32e3fb95d9e7bc7827a04bdbe8af747dd5df724c8d1b56f20654f307d2157TLS support on gRPC + JSON wiresRoadmap 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.open0featureNULLNULL2026-05-20T06:55:22ZEugene Blikhbigbes@gmail.com2026-05-20T06:55:22ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ns020b6fc12f33291102415f4213204ede198952347fae1b7e670b587ba2f267a73iproto-verify: etcd_maintenance_defragment vs Maintenance.DefragmentAdd 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.open3taskNULLNULL2026-05-19T14:54:35ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:35ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-nwl3f54509527d06071750dbdddfdcafe415133385b9549ce08b80b06cc16f9d6cfiproto-verify: etcd_user_revoke_role vs Auth.UserRevokeRoleAdd 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.open3taskNULLNULL2026-05-19T14:54:11ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:11ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ovob02eee9877621d78af7f66286e7ff63fc6564aac6beeca0cb795fe667217cb17Learner: 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.open2taskNULLNULL2026-05-20T06:45:17ZEugene Blikhbigbes@gmail.com2026-05-20T06:45:17ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ovtdb6cf24009cca490a9e5a89f705f27d73388ddfcc3513448452e373522faeeb5iproto-verify: etcd_member_remove vs Cluster.MemberRemoveAdd 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.open3taskNULLNULL2026-05-19T14:54:21ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:21ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-ozm88152e03bc9011e822aa42ffc9212e11e04a9788bd5d40d5312f3e47da59657ciproto-verify: etcd_user_list vs Auth.UserListAdd 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.open3taskNULLNULL2026-05-19T14:54:09ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:09ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-p3sd7ab326ea50217052ff7528067d9bda449d1d177009210c5b6dc67df52f33a52iproto-verify: etcd_election_leader vs Election.LeaderAdd 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.open3taskNULLNULL2026-05-19T14:54:48ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:48ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-q5f722c317df5aebe05f32f99bf226d4b916604f1518089bea768b2ed206866ecd3Learner: 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.open2taskNULLNULL2026-05-20T06:45:16ZEugene Blikhbigbes@gmail.com2026-05-20T06:45:16ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-rzh26beb784e16ef7c22030f27a08fe4e55b5e0453b6cd19af9df1ffd97a8bb3235iproto-impl: etcd_maintenance_status vs Maintenance.StatusWrap 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.open3taskNULLNULL2026-05-19T14:54:32ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:32ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-rzr3973dcbaf27d8ffaf25bdad2afcfcbfeb9e6deb07cd8ecf62c5a6446247c3468nghttp2 unary send-path rewrite — close parallel KVGet gap, drop jit.offParallel 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.open2taskNULLNULL2026-05-19T13:34:42ZEugene Blikhbigbes@gmail.com2026-05-19T13:34:42ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-rzs63c2e0e3f3c883b2db5734e851457a1f568e3a1ebb871de515f13411bd7ecbd9iproto-impl: etcd_member_update vs Cluster.MemberUpdateWrap 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.open3taskNULLNULL2026-05-19T14:54:23ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:23ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-sdtce9fb24507b45a493bd9ffc4a4ab22edafe46b9e41a95b2813bb6b2016b0ccc8iproto-verify: etcd_auth_status vs Auth.AuthStatusAdd 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.open3taskNULLNULL2026-05-19T14:54:04ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:04ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-sqve03dd24141b120acf0cc989ed396918ed61284c9962f1c036f30a262a51d39e6iproto-impl: etcd_election_proclaim vs Election.ProclaimWrap 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.open3taskNULLNULL2026-05-19T14:54:46ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:46ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-sy6ff088cd8c36175c942b8e80aa7a1bfa3bdaa64bf92a9ff46f8c736505ea0b302iproto-verify: etcd_watch_pull vs Watch.Watch-pullAdd 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.open3taskNULLNULL2026-05-19T14:53:57ZEugene Blikhbigbes@gmail.com2026-05-19T14:53:57ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-tf04410402a2773378d989b3453c6d566e9ab0eb85ec6a8ba9eb21801b478e96d73iproto-impl: etcd_maintenance_hash_kv vs Maintenance.HashKVWrap the existing handler maintenance.hash_kv (already invoked by gRPC/JSON via defs.lua route etcdserverpb.Maintenance.HashKV) as a Lua global etcd_maintenance_hash_kv callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_maintenance_hash_kv', wrap('maintenance', 'hash_kv')) under the appropriate service block; append 'etcd_maintenance_hash_kv' to the funcs table so box.schema.func.create plus guest grant runs at role apply; document the wrapper in the module-level LDoc comment. If Maintenance.HashKV returns UNIMPLEMENTED today, the wrapper still gets added so the iproto caller observes the same UNIMPLEMENTED error gRPC would return. Election.Observe is server-streaming over gRPC; iproto has no stream primitive, so propose a polling shape (observe_create/_pull/_cancel) mirroring the Watch precedent at api.lua:81-83.etcd_maintenance_hash_kv is callable from net.box:call('etcd_maintenance_hash_kv', {req}) with no Lua error before handler dispatch. Successful request shape produces same successful response shape as gRPC. box.schema.func.create plus guest grant idempotent on role re-apply.Epic tarantool-etcd-w8q. Handler at app/etcd/maintenance.lua.open3taskNULLNULL2026-05-19T14:54:39ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:39ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-tt663510fbc9abb4568f1a181ec6515e1edededff7dbb3a0cf8e1f67e62b24c780dReplica route: lease / auth state mirroring (scope v1 vs later)KV is the v1 target; this issue scopes how non-KV state behaves in replica mode and what (if anything) v1 mirrors. Questions: - Leases: do we mirror upstream lease grants/TTLs/expiry so locally-served keys show correct lease attachment, or pass-through lease ops to upstream? At minimum the lease_id on replicated kvs must round-trip; full lease lifecycle mirroring may be later. - Auth: mirror upstream users/roles/permissions, or run replica reads unauthenticated/locally-authed? Decide whether auth is enforced on the replica or delegated. - Watch served to local clients: our Watch subsystem already reconstructs from kv_history, which the tail populates — confirm local watchers work transparently once KV sync lands. Output: a documented v1 scope (likely 'KV + lease_id round-trip only; auth+full-lease+ deferred') appended to docs/TODO.md, plus any follow-up issues.Likely mostly a scoping/decision issue that spawns concrete follow-ups; keep v1 KV-only.open2taskNULLNULL2026-05-20T06:17:57ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:57ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-uee9e6ca4342149c79eee16a063f881ae3eb1683b9de5774eae58d2b37bfc8bcb9bReplica route: bootstrap snapshot importOn entering replica mode, pull the full upstream keyspace once and load it into our etcd_* spaces, recording the upstream revision the snapshot was taken at (the Watch tail starts from here). Approach: a clientv3-style Range over the whole keyspace ([\\x00, \\x00) with WithRange/WithFromKey) reading at a single revision (use the header.revision from the first Range, or RangeRequest with revision pinned + paging via WithLimit + WithMinModRev/last-key continuation). Persist each kv with its create_revision/mod_revision/version/lease intact. Alternatively consume Maintenance.Snapshot if/when interop lands (tarantool-etcd-16d) — but Range is the dependency-free path for v1. Output: etcd_* spaces populated, and the 'synced through revision R' watermark persisted for the tail phase to resume from.Must preserve upstream create_revision/mod_revision/version exactly — feeds revision-alignment. Page large keyspaces to avoid one giant Range.open2taskNULLNULL2026-05-20T06:17:54ZEugene Blikhbigbes@gmail.com2026-05-20T06:17:54ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-umcd8474c3796303d77baae0a958775f27a81b09ad2e0afaa4a00084cdf0ab6b7e9Learner: config block + role plumbingAdd the role config surface for learner mode and wire validate/apply/stop in app/roles/etcd.lua. New block under app.roles.etcd: learner: enabled: false cluster_peers: ['http://etcd-a:2380', ...] # PEER (2380) URLs, not client (2379) advertise_peer_url: 'http://this-node:2380' # how the cluster reaches us peer_tls: {...} Validate: when learner.enabled, the local store refuses normal client write registration; cluster_peers + advertise_peer_url non-empty; peer URLs are well-formed. No raft/transport logic here — just config parsing, validation, and the on/off switch the other phases hang off. Mirrors the existing grpc/json/cmux config validation in app/roles/etcd.lua.Distinct from the watch-mirror config (tarantool-etcd-jg3): peer (2380) URLs not client (2379), advertise_peer_url required for the cluster to dial us back.open2taskNULLNULL2026-05-20T06:45:13ZEugene Blikhbigbes@gmail.com2026-05-20T06:45:13ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-unwf79d825d667d7493d1fbad53e65026978cea04ebcf650b8c77456f87f7698c30Tarantool metrics integrationRoadmap P0 blocker. Expose etcd-server operational metrics through Tarantool's metrics subsystem (request counts/latencies per RPC, watch/lease counts, revision, compaction, store size). Should surface via the standard Tarantool metrics collectors so existing TT monitoring (Prometheus exporter) picks them up. Consider parity with etcd's own /metrics names where it aids dashboards.Roadmap-only item; no metrics issue existed in beads.open0featureNULLNULL2026-05-20T06:55:23ZEugene Blikhbigbes@gmail.com2026-05-20T06:55:23ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-w5r3a127352109f5847f90475b493f71b010fa77a962ab2ab7fd469ed01e25e9984iproto-impl: etcd_election_campaign vs Election.CampaignWrap the existing handler election.campaign (already invoked by gRPC/JSON via defs.lua route v3electionpb.Election.Campaign) as a Lua global etcd_election_campaign callable via iproto CALL. Mechanical change in app/etcd/api.lua: add rawset(_G, 'etcd_election_campaign', wrap('election', 'campaign')) under the appropriate service block; append 'etcd_election_campaign' 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.Campaign 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_campaign is callable from net.box:call('etcd_election_campaign', {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.open3taskNULLNULL2026-05-19T14:54:43ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:43ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL
tarantool-etcd-w6za1dfa11cf641fccae10ce051a21c5eaca457020ec09cb52c85f4e5cc8d0062c1iproto-verify: etcd_election_campaign vs Election.CampaignAdd Lua testkit verification for etcd_election_campaign (mirrors gRPC v3electionpb.Election.Campaign). 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.open3taskNULLNULL2026-05-19T14:54:44ZEugene Blikhbigbes@gmail.com2026-05-19T14:54:44ZNULLNULL0NULLNULLNULL000<binary>0NULLNULLNULL0NULL