Skip to content

feat(seinodetask): GovParamChange kind (PLT-487)#405

Merged
bdchatham merged 4 commits into
mainfrom
plt-487-govparamchange
Jun 13, 2026
Merged

feat(seinodetask): GovParamChange kind (PLT-487)#405
bdchatham merged 4 commits into
mainfrom
plt-487-govparamchange

Conversation

@bdchatham

Copy link
Copy Markdown
Collaborator

Adds the GovParamChange SeiNodeTask kind — submits a ParameterChangeProposal through the controller → seictl gov-param-change sidecar task (operator-key signed), closing the only governance step still done out-of-band (the arctic-1 prop-252 flow).

Key decision — value as apiextensionsv1.JSON: changes[].value accepts any JSON shape (scalar/string/bool/object) via x-kubernetes-preserve-unknown-fields, and the controller forwards the raw bytes; the sidecar does the single string() conversion. This structurally prevents the double-encode-at-apply bug that burned the deposit on prop-252's first draft.

  • CEL: exactly-one-payload union + kind↔payload binding + enum.
  • Dispatch: govParamChangeParamssidecar.GovParamChangeTask, KeyName via resolveSigningUID.
  • Outputs: GovParamChangeOutputs defined for shape-consistency but unpopulated (chain-as-medium, like the other gov kinds).
  • Tests: unit (mapper, value single-encode for object+scalar, keyName derivation, nil-payload→ParamsBuildFailed) + envtest (CEL accept/reject, value-accepts-any-JSON with byte-identical round-trip, MinItems/MinLength, kind-immutable).
  • Bumps seictl to the merged gov-param-change build (re-pin to the tagged release once cut).

Deferred: isExpedited (honored only via NewMsgSubmitProposalWithExpedite); generic GovSubmitProposal — per-kind admission policy is cleanly expressible, an opaque generic payload is not (RBAC/permission-boundary; see design).

Design (Coral-signed-off + Brandon-approved): bdchatham-designs designs/wave/seinode-govparamchange-submit-proposal.md. Pairs with the merged seictl PR #203. Closes PLT-487.

🤖 Generated with Claude Code

Adds the GovParamChange SeiNodeTask kind — submits a ParameterChangeProposal
through the controller → seictl gov-param-change sidecar task, operator-key
signed, closing the last governance step done out-of-band.

- CRD: GovParamChangePayload + GovParamChangeEntry; changes[].value is
  apiextensionsv1.JSON (x-kubernetes-preserve-unknown-fields) so any JSON shape
  (scalar/string/bool/object) is accepted and forwarded as RAW bytes — the
  sidecar does the single string() conversion, structurally preventing the
  prop-252 double-encode-at-apply bug.
- CEL: extend exactly-one-payload union, kind↔payload binding, enum.
- Dispatch: govParamChangeParams maps the payload to sidecar.GovParamChangeTask
  (Value as json.RawMessage from .Raw), KeyName via resolveSigningUID.
- Outputs: GovParamChangeOutputs defined for shape-consistency, UNPOPULATED
  (chain-as-medium; no TaskResult output channel) — matches the other gov kinds.
- Bumps seictl to the gov-param-change build.
- Tests: unit (mapper, value single-encode for object+scalar shapes, keyName
  derivation, nil-payload ParamsBuildFailed) + envtest (CEL accept/reject,
  value-accepts-any-JSON byte-identical round-trip, MinItems/MinLength,
  kind-immutable). make manifests generate committed.

isExpedited deferred (honored only via NewMsgSubmitProposalWithExpedite); generic
GovSubmitProposal deferred (permission-boundary: per-kind admission policy is
cleanly expressible, an opaque generic payload is not).

Design: bdchatham-designs designs/wave/seinode-govparamchange-submit-proposal.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Jun 13, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Submits real on-chain governance proposals with deposits and is documented as not chain-idempotent; retries or bad JSON encoding could waste funds or submit duplicate proposals. Changes are well-tested at schema and controller boundaries but still touch production chain operations.

Overview
Adds GovParamChange as a new SeiNodeTask kind so operators can submit ParameterChangeProposal txs via the controller → seictl gov-param-change sidecar (operator-key signed), in line with existing gov upgrade/vote tasks.

The CRD/API layer introduces GovParamChangePayload with changes[].value as apiextensionsv1.JSON (any JSON shape, byte-preserving through admission). CEL union rules and CRD manifests are extended for the new kind; GovParamChangeOutputs exist for API shape but stay unpopulated in this PR.

Controller wiring maps the CR to sidecar.GovParamChangeTask: govParamChangeParams forwards param values as raw JSON bytes (single encode at the sidecar) and derives KeyName via resolveSigningUID. TaskTypeGovParamChange is registered in the task deserialize registry. seictl is bumped to a build that includes the sidecar handler.

Coverage includes unit tests (mapping, single-encode regression, deserialize round-trip) and envtest CEL/admission tests.

Reviewed by Cursor Bugbot for commit e68d0b9. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 025c9b3. Configure here.

Comment thread internal/task/seinodetask_params.go
… (review)

CRITICAL: task.go's registry omitted sidecar.TaskTypeGovParamChange, so
Deserialize would return UnknownTaskTypeError and every GovParamChange task
would fail terminally (DeserializeFailed) before reaching the sidecar — the kind
was wired into the switch but dead on the execution path (same class as the
seictl sign-tx registry miss). Add the entry (false = submit-and-poll, like the
other gov kinds).

Tests: add a Deserialize round-trip test (the guard that would have caught this)
and a multi-entry changes test (order + per-element raw-value preservation).
@bdchatham bdchatham merged commit 61dddb8 into main Jun 13, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant