6 Commits
Author SHA1 Message Date
Hanzo AI 7678daa908 docs(kmsboot): finish vendor-neutral KMS wording in DefaultFetcher 2026-06-24 08:21:09 -07:00
zeekay a59c12e5e9 scrub Liquidity branding + corona→corona (OSS brand hygiene) 2026-06-10 23:36:12 -07:00
Hanzo AI c57585ef44 fix: gofmt -s across repo (CI format check) 2026-06-02 11:39:28 -07:00
Hanzo AI 371c4704d5 kmsboot: zero opinions — fetch and inject, nothing else
Strip every check that wasn't a hard correctness requirement of the
package itself:

  - No path-template validation. {ord}/trailing-slash/{env}-rejection
    are gone. If your template is malformed, lqd's config layer will
    reject the resulting flag downstream — that's where validation
    belongs, not in a fetch shim.
  - No partial-env check. If KMS_ADDR is set, kmsboot runs. KMS_ENV
    and STAKING_KMS_PATH_TEMPLATE are passed through as-is (empty if
    unset).
  - No empty-blob check. KMS returns what KMS returns. lqd will
    complain about empty PEM bytes if the chain config needs them.
  - Config struct is gone. ConfigFromEnv is gone. Validate is gone.
    InjectWith is gone. There's nothing left to configure.

Public surface is now four entry points:

  Inject(ctx, argv) (argv, error)
  InjectWithFetcher(ctx, fetcher, argv) (argv, error)
  DefaultFetcher(ctx, addr, env) (Fetcher, error)
  PodOrdinal(podName) (int, error)

Triggers: KMS_ADDR alone gates the whole thing. Unset = no-op.

Why: Lux nodes activate all curves and crypto precompiles by default;
chain config decides which keys apply. kmsboot is a transport, not a
policy engine. The previous correctness checks were duplicating
work that lqd's config layer does better.

Tests:
  - 6 cases (down from 12): pass-through-when-no-addr, round-trip,
    path-substitution (3 pod-naming schemes), empty-bytes-pass-through
    (positive: kmsboot does NOT fail on empty), fetch-error-propagates,
    PodOrdinal (8 sub-cases).

API break vs v1.3.0: yes — Config / ConfigFromEnv / InjectWith
removed. Direct consumers update to plain Inject(). Tag this as
v1.4.0 (minor bump — kmsboot is < 1 month old and only luxfi/
node imports it).
2026-05-30 13:13:02 -07:00
Hanzo AI bb650c7685 kmsboot: policy-neutral — drop strict-PQ posture, allow classical coexist
Lux nodes activate all curves and crypto precompiles by default —
secp256k1, ed25519, sr25519, secp256r1, BLS, FROST, CGGMP21, ML-DSA,
SLH-DSA, ML-KEM, Corona, Pulsar. A validator binary can legitimately
hold both classical and post-quantum staking material at the same
time; which one a given chain consumes is decided by the chain's
genesis `SecurityProfile`, not by the staking-load layer.

kmsboot was wrong-layer enforcing a strict-PQ policy. Strip it:

  - Drop `Config.StrictPQ`. There is only one mode now.
  - Drop the classical-compat env coexistence refusal
    (`STAKING_TLS_KEY` / `STAKING_TLS_CERT` / `STAKING_SIGNER_KEY`
    can be set alongside KMS-fetched PQ material).
  - Drop the argv-override refusal. Caller-supplied
    `--staking-*-file-content` later in argv wins under standard
    last-flag-wins viper/pflag semantics — kmsboot's prepend is
    deliberate so the operator's override takes precedence.
  - Drop the exported `ClassicalStakingEnvs` package var.

What stays — these are correctness, not policy:

  - All three trigger envs must be set together (no guessing).
  - `{env}` in path template is rejected (env is a separate KMS
    dimension carried at the GetAt boundary, not a path substring).
  - Path template must contain `{ord}` and end with `/`.
  - Empty blob from KMS = hard fail (no silent partial registration).

Tests:
  - Removed: `RefusesClassicalCompat`, `RefusesOverrideFlag`,
    `StrictPQOff`.
  - Added: `AllowsClassicalCoexistence` (positive: classical envs +
    PQ kmsboot succeeds), `PrependsBeforeUserOverride` (positive:
    operator-supplied flag survives at tail of argv).
  - 12 cases now pass; same coverage of correctness invariants.

Closes the gap between kmsboot's behavior and Lux's design: the
package fetches and injects; chain-config decides which keys apply.
2026-05-30 09:19:28 -07:00
Hanzo AI 17b0d9132d feat(kmsboot): boot-time staking-identity loader for any Lux-based node
New package `github.com/luxfi/staking/kmsboot` factors out the ZAP-
native KMS fetch + content-flag injection that luxfi/node had
shipped inline. Every Lux-derived validator binary (lqd, hanzo, zoo,
Lux itself, any fork) can now wire ZAP-native strict-PQ staking
identity load in three lines:

    argv := os.Args[1:]
    if newArgv, err := kmsboot.Inject(ctx, argv); err != nil {
        fmt.Fprintf(os.Stderr, "kmsboot: %s\n", err)
        os.Exit(1)
    } else {
        argv = newArgv
    }
    // ... rest of node init

Surface:

  - `Inject(ctx, argv) -> argv` — env-driven; no-op when none of
    KMS_ADDR/KMS_ENV/STAKING_KMS_PATH_TEMPLATE are set.
  - `InjectWith(ctx, cfg, argv)` — explicit Config; uses
    DefaultFetcher.
  - `InjectWithFetcher(ctx, cfg, fetcher, argv)` — explicit Fetcher;
    suitable for tests + non-default KMS transports.
  - `ConfigFromEnv()` + `Config.Validate()`.
  - `Fetcher` interface + `DefaultFetcher(ctx, addr, env)` wrapping
    `github.com/luxfi/kms/pkg/zapclient`.
  - `PodOrdinal(podName)` exposed for callers that derive the
    ordinal themselves.

Strict-PQ posture (default on; opt-out via Config.StrictPQ=false for
tests):
  - All three trigger envs must be set together.
  - `{env}` in path template is rejected — env is a separate KMS
    dimension carried at the GetAt boundary.
  - Path template must contain `{ord}` and end with `/`.
  - Classical-compat envs (STAKING_TLS_KEY/CERT, STAKING_SIGNER_KEY)
    present alongside kmsboot config = hard fail.
  - Pre-existing --staking-*-file-content flag on argv = hard fail.
  - Empty blob from KMS = hard fail.

Tests (13 cases, all passing):
  - happy round-trip + path substitution.
  - env-driven pass-through when no env.
  - partial-env table (6 cases).
  - template validation (env-in-template + format).
  - classical-compat refusal.
  - argv-override refusal.
  - empty-blob fail-closed.
  - StrictPQ-off bypass.
  - PodOrdinal (8 cases: lqd-N, hanzo-N, zoo-validator-N, empty,
    no-dash, trailing-dash, non-numeric).
  - DefaultFetcher empty-env hard fail.
  - fetcher Get error propagation.

go.mod: + github.com/luxfi/kms v1.9.9 (+ transitive zap, miekg/dns).
2026-05-30 08:18:16 -07:00