|
| 1 | +# Tracker CLI I/O Contract |
| 2 | + |
| 3 | +Status: Active |
| 4 | + |
| 5 | +Scope: console/tracker-client commands, with explicit emphasis on tracker checker behavior. |
| 6 | + |
| 7 | +## Purpose |
| 8 | + |
| 9 | +Define stable rules for: |
| 10 | + |
| 11 | +- output format |
| 12 | +- stdout/stderr channel usage |
| 13 | +- error payload structure |
| 14 | +- process exit codes |
| 15 | + |
| 16 | +This contract is designed for automation-first CLI usage and progressive adoption. |
| 17 | + |
| 18 | +## Core Rules |
| 19 | + |
| 20 | +### JSON-first output |
| 21 | + |
| 22 | +- JSON is the default output format for command results. |
| 23 | +- Result payloads on stdout are machine-consumable. |
| 24 | + |
| 25 | +### Channel usage |
| 26 | + |
| 27 | +- stdout: |
| 28 | + - final command results |
| 29 | + - structured status/results intended for downstream processing |
| 30 | +- stderr: |
| 31 | + - progress reporting |
| 32 | + - diagnostics and warnings |
| 33 | + - application error output |
| 34 | + |
| 35 | +### Monitor/progress events |
| 36 | + |
| 37 | +For monitor commands (for example `tracker_checker monitor udp`): |
| 38 | + |
| 39 | +- Per-probe progress is emitted as NDJSON style: one JSON object per line. |
| 40 | +- Per-probe progress events go to stderr. |
| 41 | +- Final aggregate summary goes to stdout as JSON. |
| 42 | + |
| 43 | +## Error Payload Schema |
| 44 | + |
| 45 | +Application errors should use this envelope: |
| 46 | + |
| 47 | +```json |
| 48 | +{ "error": { "kind": "string", "source": "string", "message": "string" } } |
| 49 | +``` |
| 50 | + |
| 51 | +Field meaning: |
| 52 | + |
| 53 | +- kind: machine-readable error category (for example `invalid_configuration`) |
| 54 | +- source: where the error originated (for example `TORRUST_CHECKER_CONFIG`, `config_path`, `runtime`) |
| 55 | +- message: human-readable detail |
| 56 | + |
| 57 | +## Exit Codes |
| 58 | + |
| 59 | +Exit codes represent CLI app execution status. |
| 60 | + |
| 61 | +- 0: command executed successfully (tracker failures can still be present in JSON results) |
| 62 | +- 1: generic application/runtime failure |
| 63 | +- 2: invalid tracker checker configuration/input |
| 64 | + |
| 65 | +Important: |
| 66 | + |
| 67 | +- Tracker endpoint failures do not map to non-zero process exit codes. |
| 68 | +- Tracker endpoint failures are part of result JSON payloads. |
| 69 | + |
| 70 | +## Distinguishing App Errors vs Tracker Failures |
| 71 | + |
| 72 | +- App errors: |
| 73 | + - invalid CLI/config input |
| 74 | + - internal command failures |
| 75 | + - serialization/runtime failures |
| 76 | + - reported via stderr error JSON and non-zero exit code |
| 77 | +- Tracker failures: |
| 78 | + - timeout |
| 79 | + - connection refused |
| 80 | + - non-success status from tracker endpoint |
| 81 | + - reported inside stdout result JSON, exit code remains 0 |
| 82 | + |
| 83 | +## Stability and Migration |
| 84 | + |
| 85 | +- New features and subcommands must comply with this contract. |
| 86 | +- Legacy behavior is migrated progressively. |
| 87 | +- Contract changes should remain backward compatible; if a breaking change is required, |
| 88 | + introduce a schema version and migration note. |
| 89 | + |
| 90 | +## Auditability Requirements |
| 91 | + |
| 92 | +This contract is intended to be auditable. |
| 93 | + |
| 94 | +- Prefer explicit structured payloads over ad-hoc text messages. |
| 95 | +- Keep field names stable once published. |
| 96 | +- If any required field changes, bump a schema version and document migration steps. |
| 97 | + |
| 98 | +Recommended metadata fields for auditable outputs: |
| 99 | + |
| 100 | +- `schema_version` |
| 101 | +- `command` |
| 102 | +- `timestamp` |
| 103 | +- `run_id` |
| 104 | + |
| 105 | +These fields can be added progressively as commands are migrated. |
| 106 | + |
| 107 | +## Verification Strategy |
| 108 | + |
| 109 | +### Current repository phase |
| 110 | + |
| 111 | +- Contract conformance is validated by documentation reviews and issue-level acceptance criteria. |
| 112 | +- New feature specs should include explicit checks for: |
| 113 | + - stdout/stderr channel behavior |
| 114 | + - JSON envelope conformance |
| 115 | + - exit-code semantics |
| 116 | + |
| 117 | +### Post-extraction phase (target) |
| 118 | + |
| 119 | +When `console/tracker-client` is extracted to its own repository, add dedicated E2E conformance |
| 120 | +tests for this contract. |
| 121 | + |
| 122 | +Recommended E2E coverage: |
| 123 | + |
| 124 | +- golden stdout/stderr fixtures for representative command runs |
| 125 | +- exit-code assertions (`0`, `1`, `2`) |
| 126 | +- NDJSON per-line validation for monitor probe events |
| 127 | +- JSON schema validation for final summaries and error envelopes |
| 128 | + |
| 129 | +Until extraction, this remains a planned verification step. |
| 130 | + |
| 131 | +## Examples |
| 132 | + |
| 133 | +### Example 1: Successful run with tracker failures |
| 134 | + |
| 135 | +```text |
| 136 | +stdout: |
| 137 | +{"udp_trackers":[{"url":"udp://127.0.0.1:6969","status":{"code":"timeout","message":"announce timeout"}}]} |
| 138 | +
|
| 139 | +stderr: |
| 140 | +{"event":"probe","url":"udp://127.0.0.1:6969","result":"timeout","elapsed_ms":10000} |
| 141 | +
|
| 142 | +exit code: 0 |
| 143 | +``` |
| 144 | + |
| 145 | +### Example 2: Invalid configuration |
| 146 | + |
| 147 | +```text |
| 148 | +stdout: |
| 149 | +
|
| 150 | +stderr: |
| 151 | +{"error":{"kind":"invalid_configuration","source":"TORRUST_CHECKER_CONFIG","message":"JSON parse error: trailing comma at line 7 column 5"}} |
| 152 | +
|
| 153 | +exit code: 2 |
| 154 | +``` |
| 155 | + |
| 156 | +### Example 3: Generic application failure |
| 157 | + |
| 158 | +```text |
| 159 | +stdout: |
| 160 | +
|
| 161 | +stderr: |
| 162 | +{"error":{"kind":"runtime_failure","source":"runtime","message":"failed to initialize async runtime"}} |
| 163 | +
|
| 164 | +exit code: 1 |
| 165 | +``` |
0 commit comments