Problem
Operators today run seienv vote / seienv propose-upgrade (in slanders/seienv) to perform fleet-wide governance operations against EC2 validators via SSH. With validators migrating to Kubernetes via sei-k8s-controller, the canonical operator tool going forward is seictl. seictl does not yet expose governance commands — it needs gov subcommands that resolve a SeiNode's sidecar URL from the K8s API and submit the sign-tx tasks introduced in the sister issue.
Impact
- User-visible replacement for
seienv vote / seienv propose-upgrade.
- Closes the loop on the K8s-native validator-governance workflow.
- Without it, the sidecar task surface exists but there's no ergonomic way for human operators to call it.
Relevant experts
- platform-engineer — K8s client integration, kubeconfig handling, sidecar discovery
- product-engineer — CLI ergonomics, fan-out across deployments
Proposed approach
- New top-level cobra command
seictl gov in cmd/gov/ with subcommands:
seictl gov vote <proposal-id> <yes|no|abstain|no_with_veto> --validator <seinode-name> [--namespace <ns>] [--fees <fees>] [--memo <memo>]
seictl gov submit-proposal software-upgrade <name> --validator <seinode-name> --height <h> [--info <url>] [--deposit <amt>] [--fees <fees>]
seictl gov deposit <proposal-id> <amount> --validator <seinode-name> [--fees <fees>]
- Fan-out flags for fleet-wide ops (mirrors
seienv's implicit fan-out):
--deployment <seinodedeployment-name> — resolves all SeiNodes owned by the deployment and submits in parallel
--threads N — parallelism cap (default 10)
- Sidecar discovery: K8s client (controller-runtime or client-go) fetches the SeiNode, resolves its headless Service DNS or Pod IP, constructs the sidecar URL (
http://<seinode>-0.<seinode>.<ns>.svc.cluster.local:7777). Existing NewSidecarClientFromPodDNS helper covers this shape.
- Kubeconfig: uses standard
clientcmd resolution (KUBECONFIG env, ~/.kube/config, in-cluster service-account if running in a pod).
- Output: task UUID printed immediately; if
--wait is passed (default true), polls task status until terminal and prints {txHash, height, rawLog}.
- Idempotency: caller-supplied UUID via
--task-id flag; CLI auto-generates and prints if not provided. Enables operator retry without double-voting.
- Error handling: surface sidecar task errors verbatim; on partial-failure across a fleet fan-out, print a per-validator status table and exit non-zero.
Acceptance criteria
Out of scope
- Non-gov tx commands (staking, distribution, IBC) — same pattern, separate issues
- Proposal types beyond
software-upgrade in the initial cut (param-change, community-pool, text proposals) — additive later
- Web UI / dashboard
- Authn handshake — wires in when "Sidecar authn + authz middleware" lands; until then, CLI calls the unauthenticated endpoint
References
- Coral session 2026-05-11
- Predecessor:
slanders/seienv cmd/vote.go, cmd/propose.go, propose.sh, cheatsheet.md
- Sister issue: sidecar sign-tx task family (this repo)
- Sidecar discovery pattern:
sidecar/client/client.go (NewSidecarClientFromPodDNS)
- Cobra command structure:
main.go:43-52
Sequencing
Phase 1, step 4 of 5 in the governance-flow migration. Depends on step 3 (sign-tx task family). Step 5 (authn) is the final hardening pass and lands after this.
Problem
Operators today run
seienv vote/seienv propose-upgrade(inslanders/seienv) to perform fleet-wide governance operations against EC2 validators via SSH. With validators migrating to Kubernetes viasei-k8s-controller, the canonical operator tool going forward isseictl.seictldoes not yet expose governance commands — it needsgovsubcommands that resolve a SeiNode's sidecar URL from the K8s API and submit the sign-tx tasks introduced in the sister issue.Impact
seienv vote/seienv propose-upgrade.Relevant experts
Proposed approach
seictl govincmd/gov/with subcommands:seictl gov vote <proposal-id> <yes|no|abstain|no_with_veto> --validator <seinode-name> [--namespace <ns>] [--fees <fees>] [--memo <memo>]seictl gov submit-proposal software-upgrade <name> --validator <seinode-name> --height <h> [--info <url>] [--deposit <amt>] [--fees <fees>]seictl gov deposit <proposal-id> <amount> --validator <seinode-name> [--fees <fees>]seienv's implicit fan-out):--deployment <seinodedeployment-name>— resolves all SeiNodes owned by the deployment and submits in parallel--threads N— parallelism cap (default 10)http://<seinode>-0.<seinode>.<ns>.svc.cluster.local:7777). ExistingNewSidecarClientFromPodDNShelper covers this shape.clientcmdresolution (KUBECONFIG env,~/.kube/config, in-cluster service-account if running in a pod).--waitis passed (default true), polls task status until terminal and prints{txHash, height, rawLog}.--task-idflag; CLI auto-generates and prints if not provided. Enables operator retry without double-voting.Acceptance criteria
vote,submit-proposal software-upgrade,deposit)--deploymentfleet fan-out modes work--task-idworks as documenteddocs/gov.mdmirroringslanders/seienv/cheatsheet.mdgovernance sectionOut of scope
software-upgradein the initial cut (param-change, community-pool, text proposals) — additive laterReferences
slanders/seienvcmd/vote.go,cmd/propose.go,propose.sh,cheatsheet.mdsidecar/client/client.go(NewSidecarClientFromPodDNS)main.go:43-52Sequencing
Phase 1, step 4 of 5 in the governance-flow migration. Depends on step 3 (sign-tx task family). Step 5 (authn) is the final hardening pass and lands after this.