Skip to content

healthcheck reports ready: true on an adminless contract: the readiness signal ignores governance-dead state #522

Description

@usmanimamu17-create

Problem

healthcheck (src/lib.rs) decides readiness from the storage version alone:

pub fn healthcheck(env: Env) -> HealthcheckResult {
    let stored_version: Option<u32> = env.storage().instance().get(&STORAGE_VERSION_KEY);
    let (ready, status) = match stored_version {
        None => (false, symbol_short!("noinit")),
        Some(v) if v != STORAGE_VERSION => (false, symbol_short!("migrate")),
        Some(_) => (true, symbol_short!("ok")),
    };
    ...
}

After renounce_admin (which removes ADMIN_KEY and leaves the contract with no admin and no pending admin — the batch 08 companion issue shows the pending-operator hole), the storage version is still current, so healthcheck returns ready: true for a contract whose admin-gated functions are permanently locked.

Consequences:

  • Load-balancer probes certify a governance-dead contract: the documented use is "simple load-balancer probes"; a contract that can never be reconfigured, unpaused (pause is admin-gated), or migrated reports ok, so operators get no alert that the contract is in a terminal state.
  • The readiness definition is narrower than the word: "ready" implies operational; the check covers only init/version posture, not pause, freeze, or role state — and the docstring doesn't say so.
  • The renounce state is unmonitorable: the companion issue documents that adminless contracts are NotInitialized-like on admin reads; the health endpoint is the natural place to surface that state, but it is silent.

Root cause

healthcheck was written to mirror get_version_info's minimal version posture; governance state (admin presence) was never included in the readiness definition.

Why this is architecturally hard

  1. Expanding readiness (e.g. ready: false with a new noadmin status when ADMIN_KEY is absent) is a behavior change for probes that currently expect ok for any initialized contract; the status symbol vocabulary must be extended (an additive change to HealthcheckResult's semantics, and the status values should be documented).
  2. There is a design question of how many states "ready" should encode: version, pause, freeze, roles — each addition makes the probe more informative but the endpoint's simplicity (its stated virtue) erodes.
  3. The get_contract_info needs_migration unreachability companion issue shows the same class of "struct field exists but the guard errors first" — the health and info endpoints should share one documented readiness model.

Acceptance criteria

  • An adminless contract does not report ready: true (or the readiness definition is documented to exclude governance state, with a separate signal added).
  • The status vocabulary is documented.
  • Tests cover healthcheck after renounce_admin.

Out of scope

The renounce pending-operator hole (companion issue in batch 08) and consolidating the readiness/version endpoints (companion issue in batch 03).

Getting started

just test

Good first files to read: apexchainx_calculator/src/lib.rs (healthcheck, renounce_admin), apexchainx_calculator/src/governance.rs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardStellar WaveIssues in the Stellar wave programThird CampaignCampaign: Third Campaignarea/observabilityImported campaign issue labelpriority/lowImported campaign issue label

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions