Conversation
New workspace member that holds the shared HTTP transport + foundational types for the upcoming operator binaries (trace-commons-review, trace-commons-worker, trace-commons-admin, trace-commons-tenant). These binaries take over the operator-side CLI surface that was pruned from Ironclaw's reborn trace client in nearai/ironclaw#3738. Surface in this PR: - Client with bearer-token resolution from an env var (never logged), host-allowlist enforcement, and typed error mapping for the server's {"error": "<Label>"} refusal envelope. - Error taxonomy: BearerMissing, InvalidEndpoint, HostNotAllowed, Transport, HttpFailure, ServerLabel, MalformedResponse. Each carries a user_diagnostic() that strips query strings + fragments. - HostAllowlist with exact-match semantics, case-insensitive, sourced from --allowed-hosts or TRACE_COMMONS_ALLOWED_HOSTS. - Output helpers: JsonEnvelope wrapper for --json mode, ASCII table renderer, key-value renderer for single-record commands. Per-endpoint typed request/response structs land in PR #2 (reviewer + admin) and PR #3 (worker + tenant). When a struct turns out to be shared across binaries it migrates back here. Verification: - cargo check --workspace --all-targets under -D warnings: clean - cargo test -p trace-commons-operator-client: 30 passed - cargo clippy -p trace-commons-operator-client --all-targets -- -D warnings: clean
zmanian
added a commit
that referenced
this pull request
May 20, 2026
CI on PR #124 surfaced fmt diffs across the operator-client foundation and the review/admin/worker binaries. Applied cargo fmt --all to bring the stack into compliance. Pure formatting; zero behavior change.
zmanian
added a commit
that referenced
this pull request
May 20, 2026
Lands the four-PR stack (#124, #125, #126, #127) as a single squash commit on main. ## What's in this squash **1. `trace-commons-operator-client` foundation crate** (was #124) - `Client` wrapper around `reqwest::Client` with bearer-token resolution from env, host allowlist enforcement, typed error mapping for `{"error": "<Label>"}` refusals. - Error taxonomy: `BearerMissing`, `InvalidEndpoint`, `HostNotAllowed`, `Transport`, `HttpFailure`, `ServerLabel`, `MalformedResponse`. `Error::user_diagnostic()` strips query strings + fragments. - `HostAllowlist` (CSV, exact-match, case-insensitive) sourced from `--allowed-hosts` or `TRACE_COMMONS_ALLOWED_HOSTS`. - Output helpers: `JsonEnvelope` wrapper for `--json` mode, ASCII table renderer, key-value block renderer. **2. `trace-commons-review` (8 cmds) + `trace-commons-admin` (12 cmds)** (was #125) - Single shared bearer per binary (`TRACE_COMMONS_REVIEWER_BEARER`, `TRACE_COMMONS_ADMIN_BEARER`). - 37 binary tests across both (parse-through, body validation, wiremock round-trips). **3. `trace-commons-worker` (8 cmds) + `trace-commons-tenant` (11 cmds)** (was #126) - Worker uses per-subcommand bearer envs (8 distinct env vars, one per route gate). Verified by `worker_per_route_bearer_resolution_uses_distinct_envs`. - Tenant uses single shared `TRACE_COMMONS_TENANT_BEARER`. - Operator runbook at `docs/operator/operator-binaries.md`. - CI smoke job `operator-binaries-smoke` in `.github/workflows/ci.yml`, sibling to `pilot-bootstrap-smoke`. **4. Privacy-filter-canary port** (was #127) - New `trace_commons_operator_client::privacy_filter` module: `PrivacyFilterAdapter` trait, `CommandPrivacyFilterAdapter`, `SafePrivacyFilterRedaction`, `adapter_from_env`, `canary_leaked_tokens`. Wire shapes byte-identical to Ironclaw's sidecar protocol. - Dual-name env-var compat: `TRACE_COMMONS_PRIVACY_FILTER_*` canonical, `IRONCLAW_TRACE_*` legacy fallback with warn-on-use. - `trace-commons-tenant privacy-filter-canary` stub replaced with the real handler. ## Operator surface added | Binary | Cmds | Bearer model | |---|---:|---| | `trace-commons-review` | 8 | Single `TRACE_COMMONS_REVIEWER_BEARER` | | `trace-commons-admin` | 12 | Single `TRACE_COMMONS_ADMIN_BEARER` | | `trace-commons-worker` | 8 | Per-subcommand defaults | | `trace-commons-tenant` | 11 | Single `TRACE_COMMONS_TENANT_BEARER` | | **Total** | **39** | | These mirror the 39 operator commands removed from Ironclaw in nearai/ironclaw#3738. ## Verification ``` cargo check --workspace --all-targets (-D warnings) # clean cargo test --workspace --no-run (-D warnings) # clean cargo clippy --workspace --all-targets (-D warnings) # clean cargo test -p trace-commons-operator-client # 39 passed cargo test -p trace-commons-server --bins # all green bash scripts/operator/operator-smoke.sh # SmokeOperatorBinariesOK ``` Superseded PRs (closed): #124, #125, #126.
Collaborator
Author
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Context
This is PR #1 of a three-PR stack that brings operator-side CLI workflows to this repo. The 39 operator commands previously living in Ironclaw's
ironclaw traces ...surface were just pruned out of Ironclaw in nearai/ironclaw#3738 — they will re-emerge here as four standalone binaries (one per audience). This PR lays the foundation those binaries will share.What lands
New workspace member
trace-commons-operator-client:Client— wrapsreqwest::Clientwith:--endpointflag).{\"error\": \"<Label>\"}refusal envelope.BearerMissing,InvalidEndpoint,HostNotAllowed,Transport,HttpFailure,ServerLabel,MalformedResponse. Each carries a.user_diagnostic()that strips query strings + fragments for safe stderr output.HostAllowlist— exact-match, case-insensitive, sourced from--allowed-hosts <CSV>orTRACE_COMMONS_ALLOWED_HOSTS. Subdomains are not implicit matches.JsonEnvelopewrapper for--jsonmode ({ \"request\": {...}, \"data\": <server-response> }), ASCII table renderer with column auto-sizing, key-value block renderer for single-record commands.What doesn't land
Per-endpoint typed request/response structs are deferred to:
trace-commons-review(8 cmds) +trace-commons-admin(12 cmds)trace-commons-worker(8 cmds) +trace-commons-tenant(11 cmds)If a request/response struct turns out to be shared across binaries when those PRs land, it migrates back here.
Verification
Test plan
trace_upload_claim_allowlist.rsand similar reviewer/admin gate sites — flag any label naming we should reflect at the client-error level.TRACE_COMMONS_ALLOWED_HOSTSsemantics match operator expectations (currently: comma-separated, exact-match, case-insensitive, no wildcards).Out of scope
docs/operator/operator-binaries.md) — lands with PR GCS object backend + pluggable KEK trait (production gated) #2 once there's at least one binary to document.scripts/operator/operator-smoke.sh— lands with PR GCS object backend + pluggable KEK trait (production gated) #2.🤖 Generated with Claude Code