- Full ha.h: ctrl_role_t enum (CTRL_PRIMARY/CTRL_STANDBY), ha_config_t,
ha_state_t with _Atomic fields (term, role, applied_lsn, promotion
counters, watchdog_stop), pthread_mutex_t lock, and public API.
- endpoint_t* omitted from ha_state_t — including netio.h would pull
OpenSSL headers and risk circular deps; watchdog (P1-3) includes
netio.h directly where needed.
- ha_init validates: heartbeat_interval_ms >= 2000, heartbeat_timeout_ms
>= heartbeat_interval_ms, election_timeout_ms >= 500; returns -EINVAL
on bad config; zeros struct and sets initial role to CTRL_STANDBY.
- ha_fini destroys mutex; watchdog thread join deferred to P1-3.
- am_i_primary / ha_promote_to_primary / ha_demote_to_standby are
no-op stubs; cluster_t->ha field not yet wired (P1-5), so these avoid
incomplete-type dereferences until then.
- TDD: 5 new tests in test_ha_role.c confirmed RED before implementation,
all 5 GREEN after; all prior controller tests remain green.