4 Commits
Author SHA1 Message Date
zeekayandHanzo Dev 059a989892 a deadline in a test is a timeout, not a measurement
Waiting for a membership count returns the moment the count is right, so the
deadline only ever matters when the machine is slow — which is when a false
failure is least useful. Half a second was enough for this test alone and not
enough beside the rest of its package, so it passed five times in isolation
and failed the run that gates a release.

It failed three releases, two of them somebody else's, for being slow rather
than wrong.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-14 06:48:10 -07:00
zeekayandHanzo Dev 21c8030e02 a daemon's name is the daemon's, so the CLI reads it rather than spelling it
The CLI printed a fixed name in its examples and help text while already
taking that name as a parameter, so `operator` and `rpc` now interpolate what
they were handed, the way `cluster` already did.

The config file's per-env URL block goes with it. Nothing read it: EnvURLs
computes a service address from the environment's domain suffix, which is
what every command actually calls, so the block was a second unasked answer
to where a service lives. An older config still loads — an unknown key is
ignored — and its env block is dropped on the next write. The default org is
no longer a name.

The Tasks queue is named for this repo rather than written out three times.

Fixture hostnames follow the shape the operator emits, which one of those
files was already using.

crdt/privacy_fhe.go cited a PDF that is not in the tree; the two figures it
backed are in the design doc it already points at.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-13 14:16:11 -07:00
zeekay 955e04b442 infra: standardize ZAP duplex port to 9999
ZAP binary protocol duplex RPC standardizes on :9999 across every
service. Lux validator staking/RPC ports (9630/9631 mainnet, 9650/9651
devnet) are unchanged — those are luxd network protocol ports, not ZAP.

One ZAP port everywhere (was a mix of 9651/9652/9653/9633/9900).
2026-04-25 15:35:01 -07:00
zeekay 785f35d408 feat(network): wire Membership into node; router rebuilds on scale
node.Start() now subscribes to a Membership (DNS-backed by default,
static by test injection) and rebuilds the router on every change.
The transport's own reconnect loop picks up new peers naturally; we
don't push dials from the node — Membership is the authoritative
source of truth, transport follows.

Scale flow (no pod restart):
  1. kubectl scale sts foo --replicas=N  (or docker compose scale)
  2. Orchestrator DNS starts/stops resolving pod names
  3. dnsMembership's 5s poll picks up the change
  4. node.watchMembership receives updated []NodeID
  5. router.setMembers([]NodeID) — O(N log N) sort
  6. WriterFor / MembersFor return the new topology immediately

New metric: base_network_membership_size (gauge). Drops below
expected count before transport notices — useful for scale-event
dashboards.

SetMembership(m) is how tests (and embedding callers) inject a
Membership other than the default DNS one.

Tests (all with -race):
- TestNodeScaleUp          1 → 3, router rebuilds, MembersFor growth
- TestNodeScaleDown        3 → 2, dropped member leaves MembersFor
- TestNodeScaleDownToOne   3 → 1, WriterFor flips back to local
- TestNodeMembershipNotSet static BASE_PEERS path still works
2026-04-23 04:44:39 -07:00