-
Notifications
You must be signed in to change notification settings - Fork 0
feat(cli): harden operator command contract #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
797d51c
feat(cli): add strict argument parsing
mohanagy 661185d
fix(cli): accept dashed equals values
mohanagy b6148d0
feat(cli): follow redacted audit logs
mohanagy e8c99da
fix(cli): harden audit log following
mohanagy 11f22e4
fix(cli): verify complete audit cursor
mohanagy b18fc4c
fix(cli): bound audit JSONL reader memory
mohanagy ed3c972
fix(cli): make audit snapshots transactional
mohanagy fa2a9b1
fix(cli): spool audit snapshots in OS temp
mohanagy cc4e5d0
fix(cli): skip verified idle audit polls
mohanagy 0fa145d
fix(cli): respect stdout backpressure
mohanagy d4d74c3
test(cli): verify audit spool cleanup
mohanagy 7b0cfb7
fix(cli): harden audit follow lifecycle
mohanagy 18ac337
test(audit): stabilize same-inode rewrite fixture
mohanagy a525fa4
docs(audit): explain prefix rehash
mohanagy 39ef249
test(cli): cover installed binary contract
mohanagy f7e78ab
test(ci): run packed CLI contract in compatibility matrix
mohanagy c1bbedc
test(audit): make same-inode race deterministic
mohanagy 4ee9bec
test(audit): require partial snapshot spool signal
mohanagy a07be8b
fix(pack): isolate verifier from executable wrapper
mohanagy 11493cb
fix(test): bound packed consumer install
mohanagy 2488a73
fix(test): quote Windows packed binary invocation
mohanagy 1003217
fix(cli): resolve review findings
mohanagy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,44 +1,93 @@ | ||
| # CLI reference | ||
|
|
||
| Run the wrapper for an MCP client: | ||
| `miftah` is a local STDIO MCP wrapper. Run `miftah --help` for the generated command list, or `miftah <command> --help` for the options accepted by one command. The help text is the authoritative grammar for the installed version. | ||
|
|
||
| ```bash | ||
| miftah --config ~/.config/miftah/github.json | ||
| miftah serve --config ~/.config/miftah/github.json | ||
| ## Help | ||
|
|
||
| ```text | ||
| Usage: miftah [command] [options] | ||
| ``` | ||
|
|
||
| Inspect a config without starting an upstream: | ||
| The root command list is `serve`, `validate`, `doctor`, `schema`, `init`, `list-tools`, `test-profile`, `logs`, and `version`. With no command, Miftah runs `serve`. | ||
|
|
||
| `--help` and `-h` print help and exit successfully. They can appear before or after a command. Help never reads configuration, resolves secrets, or starts an upstream. | ||
|
|
||
| ## Commands | ||
|
|
||
| | Command | Required input | Options | Output and behavior | | ||
| | --- | --- | --- | --- | | ||
| | `miftah serve --config <file>` | `--config` | `--config <file>` | Runs the STDIO MCP wrapper until it is stopped. `miftah --config <file>` is the equivalent default-command form. | | ||
| | `miftah validate --config <file>` | `--config` | `--config <file>` | Validates the JSON configuration without starting an upstream. Writes a JSON object with `ok`, `name`, and `profiles`. | | ||
| | `miftah doctor --config <file>` | `--config` | `--config <file>`, `--json` | Validates configuration and checks upstream readiness. Default output is a human-readable report; `--json` writes only the JSON report. A healthy or degraded report exits `0`; a failed report exits `1`. | | ||
| | `miftah schema` | none | none | Writes the Miftah JSON Schema as pretty-printed JSON. | | ||
| | `miftah init [name]` | none | `--name <name>`, `--preset <name>`, `--output <file>` | Writes a starter configuration with exclusive creation. The positional `name` and `--name` are alternatives; the default name is `miftah-wrapper`. | | ||
| | `miftah list-tools --config <file>` | `--config` | `--config <file>`, `--profile <name>` | Starts the selected profile, discovers its upstream tools, writes a JSON array, then closes the manager. `--profile` defaults to the configured default profile. | | ||
| | `miftah test-profile --config <file>` | `--config` | `--config <file>`, `--profile <name>` | Starts and initializes one profile, writes `{"ok":true,"profile":"…"}`, then closes the manager. `--profile` defaults to the configured default profile. | | ||
| | `miftah logs --config <file>` | `--config` | `--config <file>`, `--follow` | Reads the configured audit JSONL as normalized, redacted JSONL. `--follow` continues watching it. This command does not construct an upstream manager. | | ||
| | `miftah version` | none | `--json` | Writes the package version as a bare SemVer line. `--json` is retained for automation compatibility and intentionally writes the same bare SemVer line. | | ||
|
|
||
| Every command also accepts `--help` and `-h`; those generated per-command help screens show only the options valid for that command. | ||
|
|
||
| ```bash | ||
| miftah validate --config github.json | ||
| miftah schema | ||
| ### `init` presets and paths | ||
|
|
||
| `--preset` defaults to `generic`. The named templates are `generic`, `github`, and `sentry`; an unrecognized preset name falls back to the generic template. `--output` defaults to `<name>.miftah.json`. Miftah resolves the output path from the current working directory, creates missing parent directories, and refuses to overwrite an existing file. Quote shell paths and names containing spaces: | ||
|
|
||
| ```sh | ||
| miftah init "work wrapper" --preset github --output "$HOME/Miftah configs/work wrapper.json" | ||
| miftah validate --config "$HOME/Miftah configs/work wrapper.json" | ||
| ``` | ||
|
|
||
| ## Readiness diagnostics | ||
| ### `doctor` | ||
|
|
||
| Run readiness diagnostics before deploying a configured upstream: | ||
| `doctor` checks configuration, secret references, redaction, permissions, configured audit storage, executable availability, upstream startup, discovery, and clean shutdown where applicable. Its checks have stable `code`, `status`, `target`, `explanation`, and `remediation` fields. | ||
|
|
||
| ```bash | ||
| ```sh | ||
| miftah doctor --config github.json | ||
| miftah doctor --json --config github.json | ||
| ``` | ||
|
|
||
| The default report is human-readable. For automation, emit only the pretty-printed JSON report: | ||
| The JSON report intentionally omits resolved secret values, raw configuration paths, configured upstream command arguments, and its synthetic redaction canary. | ||
|
|
||
| ```bash | ||
| miftah doctor --json --config github.json | ||
| ## Global version options | ||
|
|
||
| These forms all print the package SemVer to stdout and nothing to stderr: | ||
|
|
||
| ```sh | ||
| miftah --version | ||
| miftah -v | ||
| miftah version | ||
| miftah version --json | ||
| ``` | ||
|
|
||
| Reports are `healthy`, `degraded`, or `failed`. Every check has a stable `code`, `status`, `target`, `explanation`, and `remediation`. Doctor validates configuration and secret references, checks redaction, permissions and configured audit storage, and probes executable availability, upstream startup, discovery, and clean shutdown where applicable. | ||
| `--version` and `-v` are root options, so they cannot be combined with another command. `--version --json` is accepted and also preserves the bare SemVer output. | ||
|
|
||
| ## Exit status and streams | ||
|
|
||
| Successful machine-readable commands write only their documented JSON or JSONL to stdout and keep stderr empty. Failures write diagnostics to stderr; their messages redact resolved secret values and upstream output containing them. Usage errors happen before configuration loading, secret resolution, or process startup. | ||
|
|
||
| Doctor never emits resolved secret values, raw configuration paths, configured upstream command arguments, or the per-run synthetic redaction canary in its report. A `healthy` or `degraded` report exits `0`; warnings therefore do not block automation. A `failed` report has blocking checks and exits `1`. | ||
| | Exit | Category | Examples | | ||
| | --- | --- | --- | | ||
| | `0` | Success | Help, schema, validation, successful commands, and healthy or degraded doctor reports. | | ||
| | `1` | Operation | A failed doctor report or another uncategorized operational failure. | | ||
| | `2` | Usage | Unknown flags or commands, missing option values, duplicate options, misplaced options, or a command without its required `--config`. | | ||
| | `3` | Configuration | Missing or unreadable config, invalid JSON or schema, and invalid configuration references. | | ||
| | `4` | Secret resolution | A required environment or secret provider value could not be resolved. | | ||
| | `5` | Upstream | Upstream process startup, initialization, discovery, transport, or shutdown failures. | | ||
| | `6` | Policy | Runtime policy, routing-blocked, routing-ambiguous, or confirmation-required failures. | | ||
|
|
||
| Inspect or initialize an upstream: | ||
| Configuration errors can name an unresolved environment variable so it can be repaired, but never print a resolved secret value. Code `6` is reserved for policy failures surfaced by runtime operations; no standalone diagnostic command currently performs a policy-governed MCP operation. | ||
|
|
||
| ```bash | ||
| miftah init github --preset github --output github.miftah.json | ||
| miftah list-tools --config github.miftah.json --profile work | ||
| miftah test-profile --config github.miftah.json --profile work | ||
| miftah logs --config github.miftah.json | ||
| ## Audit logs | ||
|
|
||
| `logs` resolves the same configured secret-bearing maps as runtime startup, including named upstream and non-default profile maps, before it renders an audit record. Each complete JSONL record is parsed, normalized, and redacted before output. Configured secret values, URI userinfo, fragments, and URI query values are removed or redacted; malformed or invalid UTF-8 records become a fixed valid JSON marker instead of being copied through. | ||
|
|
||
| ```sh | ||
| miftah logs --config "$HOME/Miftah configs/work wrapper.json" | ||
| miftah logs --config "$HOME/Miftah configs/work wrapper.json" --follow | ||
| ``` | ||
|
|
||
| Commands return non-zero status for unreadable, invalid, or unsafe configurations. Output is JSON where it is intended for scripts and never includes resolved secret values. | ||
| Without `--follow`, Miftah creates a stable finite snapshot before emitting it. If the file changes continually, it retries a bounded number of times and fails without emitting a mixed snapshot. Snapshot staging is private and removed after output or failure. | ||
|
|
||
| With `--follow`, Miftah polls at a bounded interval (250 ms by default), detects appends, truncation, copy-truncate rewrites, and replacement/rename rotation, and never keeps an audit file handle between polls. An absent file is treated as temporarily unavailable while following. `SIGINT` and `SIGTERM` stop the follower promptly, abandon pending output safely, remove signal listeners and temporary staging files, and do not start or signal an upstream process. | ||
|
|
||
| The reader uses fixed-size chunks and bounds an unterminated record at 64 KiB. This prevents an unbounded partial line from consuming memory, but means a record that exceeds that boundary is represented by the malformed-record marker rather than recovered. Audit output is an integrity and observability interface, not a replacement for retaining the original audit file under an external rotation and retention policy. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.