Skip to content

docs/cli.md and the binary disagree on the unattended flag, and omit the variable that controls audit commands #336

Description

@vladimirrott

Four gaps between docs/cli.md and what an operator actually gets, found by building a real nightly job from the docs alone.

1. --help and docs/cli.md state different contracts for --dangerously-skip-approval

--help says:

Implies --yes, --max-risk high and --non-interactive unless you set a lower --max-risk, which still wins.

docs/cli.md says:

--yes may now auto-approve HIGH-risk steps. The cap moves from MEDIUM to HIGH.

The second reads as though --yes still has to be typed, and never mentions --non-interactive at all. That difference changes what a script must pass, and it changes what --step-by-step combined with the flag does. Whichever is right, the other has to move.

2. The flag gates and banners subcommands that approve nothing

$ SYSKNIFE_I_ACCEPT_UNATTENDED_ROOT=1 sysknife audit export --dangerously-skip-approval
[]
  (full UNATTENDED MODE banner on stderr)

$ sysknife doctor --dangerously-skip-approval      # env var unset
sysknife: --dangerously-skip-approval was passed but SYSKNIFE_I_ACCEPT_UNATTENDED_ROOT is not set to 1.
$ echo $?
1

This is deliberate, and the reason is in the source: a flag that is sometimes silently ignored teaches people it is harmless. But docs/cli.md frames the whole section around plan execution, and the only hint is one line under Global flags saying all flags apply to every subcommand.

A wrapper that uniformly appends the flag to every invocation, which is a normal "always non-interactive" pattern, gets hard refusals on health checks and audit shipping. Say so in the Unattended mode section.

Stream separation is correct here: the banner is on stderr and stdout stays clean, so jq still parses. Only the scope is undocumented.

3. SYSKNIFE_DATABASE_PATH is missing, and SYSKNIFE_SOCKET does nothing for audit commands

$ grep -c SYSKNIFE_DATABASE_PATH docs/cli.md
0

developer-guide.md and the-audit-chain.md both document it as the way to point audit export and audit verify at a specific store, including a copied remote database. docs/cli.md's own Environment variables section never mentions it.

Worse, the reverse is implied. SYSKNIFE_SOCKET has its own entry warning about forwarded sockets, and audit verify --pubkey is described as the auditor path, so pointing SYSKNIFE_SOCKET at a particular daemon looks like it selects which trail you export. It does not. Audit commands never dial the daemon; they read a local file. In a fleet with several daemons that is a silent wrong answer.

4. --log-to is a stdout-only tee, and the doc's own example produces an empty file on failure

Running docs/cli.md's own Scripting and CI example verbatim, on a run that failed:

$ cat /tmp/.../nightly.log
        # 0 bytes

Every diagnostic line goes to stderr: the provider fallback notice, the planning status, and the final error. --log-to tees stdout only. On the one occasion an operator needs the log, it is empty, and nothing in the section says to capture stderr separately.

Scope

All four are docs/cli.md, except #1 which needs someone to decide which of the two statements is true and correct the other.

Difficulty

easy. Four sections of one file, plus reading main.rs once to settle #1.

Getting started

CONTRIBUTING.md has the build and test commands. docs/cli.md is not in the CI markdownlint list, so check it with npx markdownlint-cli2 docs/cli.md before pushing. No CLA and no copyright waiver. The project is MIT.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingeasyDifficulty: self-contained, no deep context neededgood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions