Skip to content

Index

axm_doctor

axm-doctor.

Env bootstrap + auth-status doctor (detect, propose, orchestrate).

Re-exports are resolved lazily (PEP 562 __getattr__): importing the package does NOT eager-load :mod:axm_doctor.orchestrate (which imports axm-vault) or :mod:axm_doctor.tools (which imports axm.tools.base). The stdlib-only detection surface (detect_tool / detect_auth) therefore stays reachable as the bootstrap probe even on a machine where the rest of AXM is not yet installable — the heavier symbols are imported only when first accessed.

AuthStatus

Bases: BaseModel

Frozen read-only auth state for a third-party binary.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
class AuthStatus(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """Frozen read-only auth state for a third-party binary."""

    tool: str
    state: AuthState
    login_cmd: str | None = None
    declaration_consulted: bool = Field(
        default=False,
        description="a declaration was discovered and consulted to produce this state",
    )

AuthStatusTool

Report third-party auth state — never a token value (mirror of vault).

Source code in packages/axm-doctor/src/axm_doctor/tools.py
Python
class AuthStatusTool:
    """Report third-party auth state — never a token value (mirror of vault)."""

    agent_hint = (
        "Report third-party binary auth state as {tool: {state, login_cmd}}; "
        "the token value is NEVER returned."
    )
    domain = "doctor"
    tags = frozenset({"doctor", "auth", "login"})

    @property
    def name(self) -> str:
        """Unique tool identifier."""
        return "auth_status"

    def execute(self) -> ToolResult:
        """Return value-free auth state; any error becomes a failure ToolResult."""
        try:
            auth = _auth_map()
            provenance = _credentials_map(collect_credential_provenance())
            credentials = {
                coordinate: {
                    "layer": entry["layer"],
                    "present": entry["present"],
                }
                for coordinate, entry in provenance.items()
            }
            rejections = _rejection_rows()
        except Exception as exc:  # noqa: BLE001 # MCP boundary: any error -> failure
            return ToolResult(success=False, error=str(exc))
        auth_text = "\n".join(
            f"- {tool}: {entry['state']}"
            f"{' [no declaration]' if not entry['declaration_consulted'] else ''}"
            for tool, entry in auth.items()
        )
        return ToolResult(
            success=True,
            data={
                "auth": auth,
                "undetermined": [
                    tool
                    for tool, entry in auth.items()
                    if entry["state"] == "undetermined"
                ],
                "logged_out": [
                    tool
                    for tool, entry in auth.items()
                    if entry["state"] == "logged_out"
                ],
                "credentials": credentials,
                "rejections": rejections,
            },
            text=(
                f"Third-party auth:\n{auth_text}\n\n{_credentials_text(provenance)}"
                f"{_rejections_text(rejections)}"
            ),
        )
name property

Unique tool identifier.

execute()

Return value-free auth state; any error becomes a failure ToolResult.

Source code in packages/axm-doctor/src/axm_doctor/tools.py
Python
def execute(self) -> ToolResult:
    """Return value-free auth state; any error becomes a failure ToolResult."""
    try:
        auth = _auth_map()
        provenance = _credentials_map(collect_credential_provenance())
        credentials = {
            coordinate: {
                "layer": entry["layer"],
                "present": entry["present"],
            }
            for coordinate, entry in provenance.items()
        }
        rejections = _rejection_rows()
    except Exception as exc:  # noqa: BLE001 # MCP boundary: any error -> failure
        return ToolResult(success=False, error=str(exc))
    auth_text = "\n".join(
        f"- {tool}: {entry['state']}"
        f"{' [no declaration]' if not entry['declaration_consulted'] else ''}"
        for tool, entry in auth.items()
    )
    return ToolResult(
        success=True,
        data={
            "auth": auth,
            "undetermined": [
                tool
                for tool, entry in auth.items()
                if entry["state"] == "undetermined"
            ],
            "logged_out": [
                tool
                for tool, entry in auth.items()
                if entry["state"] == "logged_out"
            ],
            "credentials": credentials,
            "rejections": rejections,
        },
        text=(
            f"Third-party auth:\n{auth_text}\n\n{_credentials_text(provenance)}"
            f"{_rejections_text(rejections)}"
        ),
    )

CredentialProvenance

Bases: BaseModel

The serving layer and presence of one credential coordinate.

Source code in packages/axm-doctor/src/axm_doctor/credentials.py
Python
class CredentialProvenance(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """The serving layer and presence of one credential coordinate."""

    coordinate: str
    kind: str = "credential"
    layer: str
    present: bool

EnvDoctorTool

Read-only env report: tool presence/version + auth + missing secrets.

Source code in packages/axm-doctor/src/axm_doctor/tools.py
Python
class EnvDoctorTool:
    """Read-only env report: tool presence/version + auth + missing secrets."""

    agent_hint = (
        "Read-only env doctor: report each external tool's presence/version, "
        "third-party auth state, and missing (value-free) secrets. Never installs."
    )
    domain = "doctor"
    tags = frozenset({"doctor", "env", "bootstrap", "detect"})

    @property
    def name(self) -> str:
        """Unique tool identifier."""
        return "env_doctor"

    def execute(self) -> ToolResult:
        """Return the full env report; any error becomes a failure ToolResult."""
        try:
            tools = {
                name: {"state": status.state, "version": status.version}
                for name in PROBED_TOOLS
                for status in (detect_tool(name),)
            }
            secrets = [secret.model_dump() for secret in missing_secrets()]
        except Exception as exc:  # noqa: BLE001 # MCP boundary: any error -> failure
            return ToolResult(success=False, error=str(exc))
        return ToolResult(
            success=True,
            data={
                "tools": tools,
                "auth": _auth_map(),
                "secrets": secrets,
                "config": _config_map(),
            },
        )
name property

Unique tool identifier.

execute()

Return the full env report; any error becomes a failure ToolResult.

Source code in packages/axm-doctor/src/axm_doctor/tools.py
Python
def execute(self) -> ToolResult:
    """Return the full env report; any error becomes a failure ToolResult."""
    try:
        tools = {
            name: {"state": status.state, "version": status.version}
            for name in PROBED_TOOLS
            for status in (detect_tool(name),)
        }
        secrets = [secret.model_dump() for secret in missing_secrets()]
    except Exception as exc:  # noqa: BLE001 # MCP boundary: any error -> failure
        return ToolResult(success=False, error=str(exc))
    return ToolResult(
        success=True,
        data={
            "tools": tools,
            "auth": _auth_map(),
            "secrets": secrets,
            "config": _config_map(),
        },
    )

GhConfigStatus

Bases: BaseModel

Frozen verdict on whether gh carries a base configuration.

configured when gh config get git_protocol exits 0, unconfigured otherwise, not_installed when the gh binary is absent. The config value itself is never read.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
class GhConfigStatus(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """Frozen verdict on whether ``gh`` carries a base configuration.

    ``configured`` when ``gh config get git_protocol`` exits 0, ``unconfigured``
    otherwise, ``not_installed`` when the ``gh`` binary is absent. The config
    value itself is never read.
    """

    state: GhConfigState

GitIdentityStatus

Bases: BaseModel

Frozen verdict on whether a git committer identity is resolvable.

state is decided from the presence of a [git].default store entry or the exit code of git config --get user.email — the identity value itself is never read.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
class GitIdentityStatus(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """Frozen verdict on whether a git committer identity is resolvable.

    ``state`` is decided from the *presence* of a ``[git].default`` store entry
    or the exit code of ``git config --get user.email`` — the identity value
    itself is never read.
    """

    state: GitIdentityState

InstallPlan

Bases: BaseModel

A proposed install command for a single tool — description only.

Building a plan runs nothing. argv is the program + arguments executed as a bare exec (NO shell). fetch_url, when set, marks a script-installer plan (e.g. the uv curl | sh recipe): instead of a shell pipe, the script is downloaded to a temp file and run as sh <tmpfile> — both steps are argv execs, never shell=True. human_command is the copy-pasteable form a human would type.

Source code in packages/axm-doctor/src/axm_doctor/install.py
Python
class InstallPlan(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """A proposed install command for a single tool — description only.

    Building a plan runs nothing. ``argv`` is the program + arguments executed
    as a bare exec (NO shell). ``fetch_url``, when set, marks a script-installer
    plan (e.g. the uv ``curl | sh`` recipe): instead of a shell pipe, the script
    is downloaded to a temp file and run as ``sh <tmpfile>`` — both steps are
    argv execs, never ``shell=True``. ``human_command`` is the copy-pasteable
    form a human would type.
    """

    tool: str
    argv: list[str]
    human_command: str
    fetch_url: str | None = None

InstallResult

Bases: BaseModel

Outcome of :func:run_install.

On a dry-run (confirm=False) executed is False, returncode is None, and post_check is None — nothing was installed, so nothing is re-detected. On a confirmed run, post_check carries the re-detected :class:~axm_doctor.detect.ToolStatus.

Source code in packages/axm-doctor/src/axm_doctor/install.py
Python
class InstallResult(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """Outcome of :func:`run_install`.

    On a dry-run (``confirm=False``) ``executed`` is False, ``returncode`` is
    None, and ``post_check`` is None — nothing was installed, so nothing is
    re-detected. On a confirmed run, ``post_check`` carries the re-detected
    :class:`~axm_doctor.detect.ToolStatus`.
    """

    command: str
    executed: bool
    returncode: int | None = None
    post_check: ToolStatus | None = None

MissingSecret

Bases: BaseModel

A credential spec that resolves to "missing" across every layer.

Value-less by construction: it carries only the coordinates of the spec and a copy-pasteable recovery hint (setup_hint). required preserves the catalog distinction between indispensable and optional credentials (the catalog default is True). instance identifies the account concerned, while awaiting_instance marks a multi-instance group that declares no account yet. The secret value itself NEVER transits axm_doctor.

Source code in packages/axm-doctor/src/axm_doctor/orchestrate.py
Python
class MissingSecret(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """A credential spec that resolves to ``"missing"`` across every layer.

    Value-less by construction: it carries only the coordinates of the spec
    and a copy-pasteable recovery hint (``setup_hint``). ``required``
    preserves the catalog distinction between indispensable and optional
    credentials (the catalog default is ``True``). ``instance`` identifies
    the account concerned, while ``awaiting_instance`` marks a multi-instance
    group that declares no account yet. The secret value itself NEVER transits
    axm_doctor.
    """

    group: str
    name: str
    package: str
    setup_hint: str
    required: bool
    instance: str | None = None
    awaiting_instance: bool = False

ProvideResult

Bases: BaseModel

Outcome of :func:provide_secret, value-free by construction.

Carries only the coordinates of the credential, the storage target vault reported (prefixed keyring: or config:) and the attestation. stored is True ONLY when a post-write re-resolution of the catalog no longer reports the coordinate missing: a delegated write that raised nothing is not proof, exactly as for :class:ProvisionResult. still_missing lists the coordinates left unresolved after the call and reason names why nothing was stored (vault's refusal, or a coordinate that stayed unresolved). The supplied value NEVER appears here — the model deliberately declares no field able to hold it.

Source code in packages/axm-doctor/src/axm_doctor/orchestrate.py
Python
class ProvideResult(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """Outcome of :func:`provide_secret`, value-free by construction.

    Carries only the coordinates of the credential, the storage ``target``
    vault reported (prefixed ``keyring:`` or ``config:``) and the attestation.
    ``stored`` is True ONLY when a post-write re-resolution of the catalog no
    longer reports the coordinate missing: a delegated write that raised
    nothing is not proof, exactly as for :class:`ProvisionResult`.
    ``still_missing`` lists the coordinates left unresolved after the call and
    ``reason`` names why nothing was stored (vault's refusal, or a coordinate
    that stayed unresolved). The supplied value NEVER appears here — the model
    deliberately declares no field able to hold it.
    """

    stored: bool
    group: str
    name: str
    instance: str | None = None
    target: str | None = None
    still_missing: list[str] = []
    reason: str | None = None

ProvisionResult

Bases: BaseModel

Outcome of :func:provision_missing.

On a dry-run (confirm=False) provisioned is False and groups lists the groups it WOULD prompt for. On a confirmed run provisioned is True ONLY when a post-setup re-scan confirms every previously-missing spec now resolves — delegating to vault's setup driver is not proof the user actually supplied the secrets (they may skip/empty the prompts). still_missing lists the specs that remain unresolved after the run (always empty on a dry-run), so a partial provisioning is reported truthfully rather than as a false green.

Source code in packages/axm-doctor/src/axm_doctor/orchestrate.py
Python
class ProvisionResult(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """Outcome of :func:`provision_missing`.

    On a dry-run (``confirm=False``) ``provisioned`` is False and ``groups``
    lists the groups it WOULD prompt for. On a confirmed run ``provisioned``
    is True ONLY when a post-setup re-scan confirms every previously-missing
    spec now resolves — delegating to vault's setup driver is not proof the
    user actually supplied the secrets (they may skip/empty the prompts).
    ``still_missing`` lists the specs that remain unresolved after the run
    (always empty on a dry-run), so a partial provisioning is reported truthfully
    rather than as a false green.
    """

    provisioned: bool
    groups: list[str]
    still_missing: list[str] = []
    reason: str | None = None

ToolStatus

Bases: BaseModel

Frozen result of probing a single external tool on PATH.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
class ToolStatus(BaseModel, frozen=True):  # type: ignore[explicit-any]
    """Frozen result of probing a single external tool on ``PATH``."""

    name: str
    state: ToolState
    version: str | None = None
    path: str | None = None

__dir__()

Expose the lazily-resolvable names to dir() / autocompletion.

Source code in packages/axm-doctor/src/axm_doctor/__init__.py
Python
def __dir__() -> list[str]:
    """Expose the lazily-resolvable names to ``dir()`` / autocompletion."""
    return sorted(__all__)

__getattr__(name)

Resolve a public symbol from its submodule on first access (PEP 562).

Source code in packages/axm-doctor/src/axm_doctor/__init__.py
Python
def __getattr__(name: str) -> object:
    """Resolve a public symbol from its submodule on first access (PEP 562)."""
    module = _LAZY.get(name)
    if module is None:
        raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
    import importlib

    return getattr(importlib.import_module(f"{__name__}.{module}"), name)

collect_credential_provenance(*, probe=None)

Translate vault provenance into typed rows without carrying values.

Source code in packages/axm-doctor/src/axm_doctor/credentials.py
Python
def collect_credential_provenance(
    *, probe: ProvenanceProbe | None = None
) -> list[CredentialProvenance]:
    """Translate vault provenance into typed rows without carrying values."""
    catalog: Catalog | None = None
    provenance: Mapping[str, ProvenanceValue]
    declared_kinds: dict[str, str] = {}
    if probe is None:
        catalog = load_catalog()
        provenance = doctor_data(catalog=catalog)
        declared_kinds = _catalog_kinds(catalog)
    else:
        provenance = probe()
    rows: list[CredentialProvenance] = []
    for coordinate, entry in provenance.items():
        kind = declared_kinds.get(coordinate, "unknown")
        try:
            if kind == "unknown":
                kind = _entry_kind(entry)
            layer, present = _entry_fields(entry)
        except Exception:  # noqa: BLE001 # isolate one malformed declaration
            layer = "unknown"
            present = False
        rows.append(
            CredentialProvenance(
                coordinate=coordinate,
                kind=kind,
                layer=layer,
                present=False if layer == "missing" else present,
            )
        )
    if catalog is not None:
        rows.extend(_auth_dependency_rows(catalog))
    return rows

detect_auth(tool)

Report auth state through a package declaration when one is installed.

A tool without a declaration degrades to presence detection: an installed binary has an undetermined auth state because its session cannot be verified.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
def detect_auth(tool: str) -> AuthStatus:
    """Report auth state through a package declaration when one is installed.

    A tool without a declaration degrades to presence detection: an installed
    binary has an undetermined auth state because its session cannot be verified.
    """
    declaration = load_auth_declarations().get(tool)
    if declaration is not None:
        declared_state = _detect_declared_auth(declaration)
        return AuthStatus(
            tool=tool,
            state=declared_state,
            login_cmd=(
                declaration.login_command if declared_state == "logged_out" else None
            ),
            declaration_consulted=True,
        )

    state: AuthState = (
        "undetermined" if shutil.which(tool) is not None else "not_installed"
    )
    return AuthStatus(
        tool=tool,
        state=state,
        declaration_consulted=False,
    )

detect_gh_config()

Report whether gh carries a base config, value-free.

Probes the exit code of gh config get git_protocol (its stdout is captured and discarded). gh absent → not_installed; any OSError / SubprocessError degrades to unconfigured. This is distinct from and additional to the gh auth status login check.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
def detect_gh_config() -> GhConfigStatus:
    """Report whether ``gh`` carries a base config, value-free.

    Probes the exit code of ``gh config get git_protocol`` (its stdout is
    captured and discarded). ``gh`` absent → ``not_installed``; any
    ``OSError`` / ``SubprocessError`` degrades to ``unconfigured``. This is
    distinct from and additional to the ``gh auth status`` login check.
    """
    if shutil.which("gh") is None:
        return GhConfigStatus(state="not_installed")
    try:
        proc = subprocess.run(
            ["gh", "config", "get", "git_protocol"],  # noqa: S607 - controlled binary
            capture_output=True,
            text=True,
            timeout=_VERSION_TIMEOUT_S,
            check=False,
        )
    except (OSError, subprocess.SubprocessError):
        return GhConfigStatus(state="unconfigured")
    state: GhConfigState = "configured" if proc.returncode == 0 else "unconfigured"
    return GhConfigStatus(state=state)

detect_git_identity()

Report whether a git committer identity is resolvable, value-free.

Cheapest source first: a truthy [git].default in the axm-config store means an identity exists. Otherwise fall back to the exit code of git config --get user.email (its stdout — the email — is captured and discarded, never returned). Any missing binary / OSError / SubprocessError degrades to unconfigured without raising.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
def detect_git_identity() -> GitIdentityStatus:
    """Report whether a git committer identity is resolvable, value-free.

    Cheapest source first: a truthy ``[git].default`` in the ``axm-config``
    store means an identity exists. Otherwise fall back to the exit code of
    ``git config --get user.email`` (its stdout — the email — is captured and
    discarded, never returned). Any missing binary / ``OSError`` /
    ``SubprocessError`` degrades to ``unconfigured`` without raising.
    """
    import axm_config

    if axm_config.get("git", "default", default=None):
        return GitIdentityStatus(state="configured")
    if shutil.which("git") is None:
        return GitIdentityStatus(state="unconfigured")
    try:
        proc = subprocess.run(
            ["git", "config", "--get", "user.email"],  # noqa: S607 - controlled binary
            capture_output=True,
            text=True,
            timeout=_VERSION_TIMEOUT_S,
            check=False,
        )
    except (OSError, subprocess.SubprocessError):
        return GitIdentityStatus(state="unconfigured")
    state: GitIdentityState = "configured" if proc.returncode == 0 else "unconfigured"
    return GitIdentityStatus(state=state)

detect_tool(name)

Probe name on PATH and parse <name> --version.

Returns present with the parsed version string when found, absent otherwise. Never raises on a missing or misbehaving tool.

Source code in packages/axm-doctor/src/axm_doctor/detect.py
Python
def detect_tool(name: str) -> ToolStatus:
    """Probe ``name`` on ``PATH`` and parse ``<name> --version``.

    Returns ``present`` with the parsed version string when found, ``absent``
    otherwise. Never raises on a missing or misbehaving tool.
    """
    path = shutil.which(name)
    if path is None:
        return ToolStatus(name=name, state="absent")
    return ToolStatus(
        name=name,
        state="present",
        version=_probe_version(name),
        path=path,
    )

install_command(tool)

Return the official :class:InstallPlan for tool, or None.

Runs nothing. An unknown tool returns None rather than guessing a command.

Source code in packages/axm-doctor/src/axm_doctor/install.py
Python
def install_command(tool: str) -> InstallPlan | None:
    """Return the official :class:`InstallPlan` for ``tool``, or None.

    Runs nothing. An unknown tool returns None rather than guessing a
    command.
    """
    return _REGISTRY.get(tool)

missing_secrets()

Return the catalog specs that resolve to "missing", value-free.

Reads the vault catalog and the value-free provenance report; a spec is reported when no resolver layer supplies it. An empty catalog (the nominal state for vault today) yields [] gracefully.

Source code in packages/axm-doctor/src/axm_doctor/orchestrate.py
Python
def missing_secrets() -> list[MissingSecret]:
    """Return the catalog specs that resolve to ``"missing"``, value-free.

    Reads the vault catalog and the value-free provenance report; a spec is
    reported when no resolver layer supplies it. An empty catalog (the
    nominal state for vault today) yields ``[]`` gracefully.
    """
    catalog = load_catalog()
    provenance = doctor_data(catalog=catalog)
    missing: list[MissingSecret] = []
    for group in catalog.groups():
        if group.multi and group.instances is not None:
            declared_instances = tuple(group.instances.list_instances())
            awaiting_instance = not declared_instances
            instances: tuple[str | None, ...] = declared_instances or (None,)
        else:
            awaiting_instance = False
            instances = (None,)

        for spec in group.specs:
            if spec.kind == "auth_dependency":
                continue
            for instance in instances:
                if _is_served(provenance, group.id, spec.name, instance):
                    continue
                missing.append(
                    MissingSecret(
                        group=group.id,
                        name=spec.name,
                        package=group.package,
                        setup_hint=f"axm-vault set {group.id} {spec.name}",
                        required=spec.required,
                        instance=instance,
                        awaiting_instance=awaiting_instance,
                    )
                )
    return missing

provide_secret(*, group, name, value, instance=None)

Store a caller-supplied credential value, attested by a re-resolution.

The third provisioning capability, beside :func:missing_secrets (what is missing) and :func:provision_missing (ask a human at a terminal): here the caller already HOLDS the value. sys.stdin is never consulted, so the call works behind a web server or in a packaged app with no shell.

The write is delegated to vault's vault_set tool, which owns the sensitivity routing (SECRET to the keyring, CONFIG to axm-config, NONSENSITIVE refused as environment-only); doctor never stores a credential itself. A delegated write that did not fail is NOT proof the credential now resolves — exactly as in :func:provision_missing, truth comes from re-resolving the catalog afterwards, so a write that persisted nothing is reported as a failure rather than as a false green.

Parameters:

Name Type Description Default
group str

The credential group id, as declared by the vault catalog.

required
name str

The credential name within that group.

required
value str

The value handed to the storage layer. It is never logged, never returned and never placed on the result.

required
instance str | None

The account identity within a multi-instance group.

None

Returns:

Type Description
ProvideResult

A value-free :class:ProvideResult whose stored is True only when

ProvideResult

the post-write re-resolution no longer reports the coordinate missing.

Source code in packages/axm-doctor/src/axm_doctor/orchestrate.py
Python
def provide_secret(
    *,
    group: str,
    name: str,
    value: str,
    instance: str | None = None,
) -> ProvideResult:
    """Store a caller-supplied credential value, attested by a re-resolution.

    The third provisioning capability, beside :func:`missing_secrets` (what is
    missing) and :func:`provision_missing` (ask a human at a terminal): here
    the caller already HOLDS the value. ``sys.stdin`` is never consulted, so
    the call works behind a web server or in a packaged app with no shell.

    The write is delegated to vault's ``vault_set`` tool, which owns the
    sensitivity routing (SECRET to the keyring, CONFIG to axm-config,
    NONSENSITIVE refused as environment-only); doctor never stores a
    credential itself. A delegated write that did not fail is NOT proof the
    credential now resolves — exactly as in :func:`provision_missing`, truth
    comes from re-resolving the catalog afterwards, so a write that persisted
    nothing is reported as a failure rather than as a false green.

    Args:
        group: The credential group id, as declared by the vault catalog.
        name: The credential name within that group.
        value: The value handed to the storage layer. It is never logged,
            never returned and never placed on the result.
        instance: The account identity within a multi-instance group.

    Returns:
        A value-free :class:`ProvideResult` whose ``stored`` is True only when
        the post-write re-resolution no longer reports the coordinate missing.
    """
    coordinate = KeyringStore.username(group, name, instance)
    outcome = VaultSetTool().execute(
        group=group, name=name, value=value, instance=instance
    )
    if not outcome.success:
        refusal = outcome.error or f"vault refused to store {coordinate}"
        return ProvideResult(
            stored=False,
            group=group,
            name=name,
            instance=instance,
            still_missing=_missing_coordinates(),
            reason=refusal,
        )
    still_missing = _missing_coordinates()
    stored = coordinate not in still_missing
    reason = None if stored else f"{coordinate} is still unresolved after the write"
    return ProvideResult(
        stored=stored,
        group=group,
        name=name,
        instance=instance,
        target=_stored_target(outcome.data),
        still_missing=still_missing,
        reason=reason,
    )

provision_missing(*, confirm=False)

Plan (and on confirm execute) provisioning of missing secrets.

Collects the distinct groups owning at least one missing spec. With confirm=False it returns the plan without prompting or storing. With confirm=True it delegates to vault's :func:run_setup (one call per group, restricted via only=); doctor never stores a secret itself.

Source code in packages/axm-doctor/src/axm_doctor/orchestrate.py
Python
def provision_missing(*, confirm: bool = False) -> ProvisionResult:
    """Plan (and on ``confirm`` execute) provisioning of missing secrets.

    Collects the distinct groups owning at least one missing spec. With
    ``confirm=False`` it returns the plan without prompting or storing. With
    ``confirm=True`` it delegates to vault's :func:`run_setup` (one call per
    group, restricted via ``only=``); doctor never stores a secret itself.
    """
    groups: list[str] = []
    for secret in missing_secrets():
        if secret.group not in groups:
            groups.append(secret.group)
    if confirm and not sys.stdin.isatty():
        return ProvisionResult(
            provisioned=False,
            groups=groups,
            reason="non-interactive shell: cannot prompt for secrets",
        )
    if not confirm:
        return ProvisionResult(provisioned=False, groups=groups)
    for group in groups:
        try:
            run_setup(only=group)
        except SystemExit as exc:  # vault's setup driver aborts via SystemExit
            return ProvisionResult(
                provisioned=False,
                groups=groups,
                reason=f"vault setup aborted for {group} (exit {exc.code})",
            )
    # Re-scan: delegating to run_setup is NOT proof a secret was supplied (the
    # user may skip/empty a prompt). Truth comes from re-resolving the catalog.
    still_missing = [f"{s.group}.{s.name}" for s in missing_secrets()]
    provisioned = bool(groups) and not still_missing
    reason = None if provisioned else "some secrets remain unresolved after setup"
    return ProvisionResult(
        provisioned=provisioned,
        groups=groups,
        still_missing=still_missing,
        reason=reason if still_missing else None,
    )

run_install(plan, *, confirm=False)

Execute plan only when confirm is True; otherwise dry-run.

With the default confirm=False this NEVER installs: it returns the command it would run with executed=False and returncode=None. With confirm=True it runs the command, then re-detects the tool via :func:~axm_doctor.detect.detect_tool and reports the post-install state.

Source code in packages/axm-doctor/src/axm_doctor/install.py
Python
def run_install(plan: InstallPlan, *, confirm: bool = False) -> InstallResult:
    """Execute ``plan`` only when ``confirm is True``; otherwise dry-run.

    With the default ``confirm=False`` this NEVER installs: it returns the
    command it *would* run with ``executed=False`` and ``returncode=None``.
    With ``confirm=True`` it runs the command, then re-detects the tool via
    :func:`~axm_doctor.detect.detect_tool` and reports the post-install state.
    """
    if not confirm:
        return InstallResult(command=plan.human_command, executed=False)

    returncode = _run_fetch_install(plan) if plan.fetch_url else _run_argv(plan.argv)
    return InstallResult(
        command=plan.human_command,
        executed=True,
        returncode=returncode,
        post_check=detect_tool(plan.tool),
    )