Skip to content

feat(nodedeployment): support flat-key rendering for spec.genesis.overrides #183

@bdchatham

Description

@bdchatham

Problem

spec.genesis.overrides (plumbed end-to-end via sei-k8s-controller#270 and seictl#181 on 2026-05-18) requires a flat map[string]<JSON> shape with dotted cosmos-module-path KEYS — the dots live INSIDE the key string (e.g. "staking.params.unbonding_time": "600s"). The sidecar's applyGenesisOverrides enforces this: keys must be module.field[.field...], first segment must be a cosmos module in app_state.

seictl nd apply --set spec.genesis.overrides.<path>=<value> cannot emit this shape. --set's path parser splits unconditionally on . and builds a nested map, producing:

overrides:
  staking:
    params:
      unbonding_time: 3600s

The sidecar rejects this with key "staking" must be of the form module.field[.field...] (the top-level key is just staking, a single token).

Impact

Engineers using the harbor-dev skill (or just reading the seictl CLI surface) have no working CLI path to set genesis params. Today's first attempt at the new field (harbor-engineering-workspace#14 → #16) had to:

  1. Render the base SND via seictl nd apply --dry-run
  2. Strip server-side fields with yq
  3. Manually edit the YAML or patch with another yq invocation to inject flat keys
  4. Commit + open PR

That's a four-step workflow where the harbor-dev skill historically promised one. The Tide repo's harbor-dev skill docs were corrected in sei-protocol/Tide#78, but the underlying CLI gap remains.

Relevant experts

  • product-engineer — flag design and CLI ergonomics
  • kubernetes-specialist — interaction with the controller's CRD shape (which accepts arbitrary JSON values)

Proposed approach

Add a dedicated --genesis-override <key>=<value> flag to seictl nd apply, mirroring the existing --override flag for spec.template.spec.overrides. The key is the literal flat-key string; the value is the raw JSON the sidecar should write at that path.

seictl nd apply <name> --preset genesis-chain \
  --chain-id <id> --image <ref> \
  --genesis-override staking.params.unbonding_time=600s \
  --genesis-override bank.params.default_send_enabled=true \
  --genesis-override gov.params.voting_period=120s \
  -n eng-<alias>

Implementation outline (matches the shape of the existing --override handler in nodedeployment/preset.go):

  • Add genesisOverrides []string to renderArgs
  • After the main render path, walk the slice; for each <key>=<value> entry:
    • Validate the key with the same regex/rule as the sidecar (module.field[.field...], no empty segments)
    • Parse the value as JSON if it parses, else as a string
    • Set spec.genesis.overrides[key] = parsed-value (the key is a literal map key containing dots; no path splitting)
  • Reject --genesis-override when --preset != genesis-chain (only that preset's CR has spec.genesis)
  • Document in seictl-cli.md (the in-repo docs) and the harbor-dev skill

Acceptance criteria

  • seictl nd apply ... --genesis-override staking.params.unbonding_time=600s renders YAML containing "staking.params.unbonding_time": "600s" at spec.genesis.overrides.
  • A unit test in nodedeployment/preset_test.go covering: string value, numeric value, bool value, single-segment key rejected, empty value rejected, used with non-genesis-chain preset rejected.
  • harbor-dev skill docs in sei-protocol/Tide updated to reference --genesis-override as the canonical path (replaces the yq-patching workaround).

Out of scope

  • Reaching consensus_params.* (sibling to app_state in genesis.json, not under any cosmos module). Different mechanism entirely; file separately if/when there's demand.
  • Changing --set's path parser to support escaped dots. Backward-compat-risky and the --override/--genesis-override pattern is cleaner.

References

  • Today's surfacing PR: sei-protocol/harbor-engineering-workspace#14 (broke) → Implement await validator command #16 (fix with manual flat keys)
  • Skill docs correction: sei-protocol/Tide#78
  • Sidecar validator: sidecar/tasks/genesis_overrides.go (applyGenesisOverrides)
  • Existing --override flag pattern: nodedeployment/preset.go (overrides []string, applyOverride)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions