@nettoolskit/control
v0.0.1-preview.1
Published
Machine control plane and adapter host foundation for NetToolsKit.
Downloads
83
Maintainers
Readme
nettoolskit-control
Machine control-plane and adapter host repository for NetToolsKit.
This repository owns machine registration, worker coordination, command allowlists, task queues, leases, approvals, evidence capture, audit records, event-bus integration, and adapter dispatch orchestration.
Current Slice
The current implementation establishes the first adapter host and local
control-plane foundation surface over nettoolskit-contracts.
| Area | Ownership |
| --- | --- |
| adapters::ToolAdapter | Trait for concrete tool wrappers such as Codex CLI, Git, Cargo, and screenshot adapters. |
| adapters::AdapterCatalog | Read-only catalog for supported adapter kinds. |
| adapters::StaticAdapterCatalog | Bootstrap catalog for local development and tests. |
| adapters::AdapterDispatchError | Control-owned dispatch error that can produce skipped evidence results. |
| adapters::plan_adapter_invocation | Local-only adapter invocation planning with catalog, command policy, timeout, and secret-shaped argument validation. |
| approvals::InMemoryApprovalLedger | Bounded approval decision recording for later command and service-action execution. |
| machines::InMemoryMachineRegistry | Deterministic machine registration, heartbeat, lookup, and schedulable-machine selection. |
| operations::plan_machine_operation | Dry-run machine operation planning with approval, service, command, and secret-shaped input safeguards. |
| operations::build_machine_operation_observation | Bounded worker/agent observation normalization with output suppression by default. |
| operations::build_machine_operation_replay_report | Redaction-safe replay report construction across plan, approval, dispatch, and observation records. |
| services::InMemoryServiceRegistry | Service records, service status, service operation allowlists, and machine-scoped service lookup. |
| commands::CommandAllowlist | Command policy evaluation for approved channels, mutating operations, and dry-run protection. |
| leases::build_task_lease | Validated task lease construction over shared fleet task contracts. |
| queue::InMemoryTaskQueue | In-memory task intake, lease assignment, running transition, terminal completion, and lease expiry boundary. |
| audit::InMemoryAuditLog | Append-only audit event collection for local planning and tests. |
| evidence::EvidenceBundle | Structured evidence collection with artifact references and bounded summaries. |
| events::InMemoryEventOutbox | Control-owned event outbox and dry-run publish batch planning over shared event envelopes. |
| worker::InMemoryWorkerRegistry | Worker telemetry, freshness, capacity, and schedulable-worker selection without runtime execution. |
| server::ControlServerView | Read-only control server inventory and service-action planning without HTTP, SSH, Docker, or process execution. |
| alerts::plan_control_alerts | Local alert notification planning from supplied control signals and route labels without publishing. |
| smoke::plan_smoke | Scoped smoke probe planning and CommandOutputEnvelope emission without DNS, HTTP, TCP, SSH, Docker, database, or secret-store calls. |
| smoke::live::run_live_network_probes | Explicit live DNS/TCP/HTTP/HTTPS smoke observations without shell, SSH authentication, Docker, Portainer, WireGuard, external HTTP clients, or secret stores. |
| smoke::live::run_live_authenticated_http_probe | Explicit authenticated HTTP(S) smoke observation that logs in, validates a configured route, and emits only redacted status summaries. |
| smoke::live::run_live_access_runtime_ssh_probes | Fixed read-only Access runtime SSH probes for container labels, public listener guardrails, Traefik loopback health, WireGuard interface state, RustDesk identity, Seq health, and backup dry-run evidence. |
| rustdesk::import_rustdesk_config | Local RustDesk client config plan/apply with backups, product-neutral defaults, optional templates, and redacted command output. |
Local CLI
ntk-control is the product-owned local CLI for control-plane operations. It
uses nettoolskit-cli only for shared terminal rendering primitives; command
semantics stay in this repository.
Evaluate a read-only command policy without executing anything:
cargo run --bin ntk-control -- commands evaluate --command-id service.status --summary "read service status" --mutation read-only --channel wire-guardEvaluate the DET local use gate from Harness and Assurance JSON artifacts:
cargo run --bin ntk-control -- det use-gate evaluate --summary .deployment/artifacts/harness/local-effectiveness/local-effectiveness-summary.json --assurance-gate .deployment/artifacts/assurance/det-local-effectiveness-gate.json --output .deployment/artifacts/control/det-use-gate.jsondet use-gate evaluate consumes already-produced local evidence. It does not
run DET, benchmarks, Analytics, Assurance, DevOps, Docker, npm, GitHub
Releases, shell commands, CI/CD, providers, or publication workflows.
Evaluate a mutating command request. Mutating commands require approval and a non-dry-run request, but this command still only evaluates policy:
cargo run --bin ntk-control -- commands evaluate --command-id service.restart --summary "restart managed service" --mutation mutating --channel wire-guard --allowed-channel wire-guard --approved --executePlan an allowlisted adapter invocation without executing the adapter:
cargo run --bin ntk-control -- adapters invoke plan --adapter cargo --command-id cargo.test --summary "run cargo tests" --mutation read-only --channel wire-guard --argument test --argument --lockedPreview a mutating adapter invocation with approval and a non-dry-run intent. This still only creates the plan and does not run PowerShell:
cargo run --bin ntk-control -- adapters invoke plan --adapter powershell --command-id service.restart --summary "restart managed service" --mutation mutating --channel wire-guard --approved --execute --argument Restart-Service --argument access-controlRestrict the local adapter catalog and render the CommandOutputEnvelope JSON
contract:
cargo run --bin ntk-control -- adapters invoke plan --adapter git --allow-adapter git --command-id git.status --summary "read git status" --argument status --argument --short --format jsonadapters invoke plan validates adapter catalog support, command allowlist,
channel policy, approval, dry-run intent, timeout, working directory, and
structured arguments. It rejects secret-shaped values and does not interpret
arguments as shell strings. It does not call adapter implementations, spawn
processes, call DNS, HTTPS, TCP, SSH, Docker, GitHub, MCP, service runtimes,
filesystem writers, or secret stores.
Build a local machine/service/worker inventory snapshot without probing hosts:
cargo run --bin ntk-control -- inventory snapshot --machine "id=access-vps;status=ready;capacity=2;load=0;hostname=access-vps" --service "id=access-control;machine=access-vps;kind=model-control-api;status=healthy;operations=status,collect-evidence" --worker "id=worker-access;machine=access-vps;status=ready;active=0;capacity=2"Render the same read model as JSON for a future dashboard adapter:
cargo run --bin ntk-control -- inventory snapshot --machine "id=access-vps;status=ready;capacity=2;load=0" --service "id=access-control;machine=access-vps;kind=model-control-api;status=healthy" --worker "id=worker-access;machine=access-vps;status=ready;active=0;capacity=2" --format jsonBuild a dashboard-oriented inventory view with summary cards and findings:
cargo run --bin ntk-control -- inventory dashboard --machine "id=access-vps;status=ready;capacity=2;load=0" --service "id=access-control;machine=access-vps;kind=model-control-api;status=healthy;operations=status,collect-evidence" --worker "id=worker-access;machine=access-vps;status=ready;active=0;capacity=2"Render the dashboard contract as JSON for a UI/API adapter:
cargo run --bin ntk-control -- inventory dashboard --machine "id=copilot-vps;status=ready;capacity=1;load=0" --service "id=mcp-gateway;machine=copilot-vps;kind=mcp-gateway;status=degraded" --worker "id=worker-copilot;machine=copilot-vps;status=ready" --format jsoninventory snapshot builds in-memory machine, service, worker, queue, audit,
and evidence registries from explicit arguments and then reads the existing
ControlServerView snapshot. inventory dashboard reuses that same boundary
and adds deterministic, secret-free cards and findings. Neither command probes
DNS, HTTP, TCP, SSH, Docker, Portainer, WireGuard, MCP, service runtimes, shell
commands, broker APIs, filesystem writers, or secret stores.
Plan a generic machine status operation with explicit policy context:
cargo run --bin ntk-control -- machine operation plan --machine-id machine-1 --operation status --registered-machine machine-1 --ready-channel wire-guardPreview a denied mutating service restart. Approval removes only the approval denial; this contract slice still remains dry-run only:
cargo run --bin ntk-control -- machine operation plan --machine-id machine-1 --operation service-restart --service-id svc-mcp --registered-machine machine-1 --ready-channel wire-guard --service-policy "id=svc-mcp;machine=machine-1;operations=status,restart"Render the same machine-operation contract as JSON for automation:
cargo run --bin ntk-control -- machine operation plan --request-id operation-command-json --machine-id machine-1 --operation command --command-id deploy-restart --registered-machine machine-1 --ready-channel wire-guard --allowed-command deploy-status --approved --format jsonProduce a local approval plan for a mutating operation:
cargo run --bin ntk-control -- machine operation approve --request-id operation-restart --machine-id machine-1 --operation service-restart --service-id svc-mcp --approval-id approval-operation-restart --decided-by operator-local --decided-at-unix-ms 4000 --format jsonConvert an approved operation into a dry-run dispatch envelope:
cargo run --bin ntk-control -- machine operation dispatch-plan --request-id operation-restart --machine-id machine-1 --operation service-restart --service-id svc-mcp --channel wire-guard --approval-state approved --approval-id approval-operation-restart --dispatch-id dispatch-operation-restart --registered-machine machine-1 --ready-channel wire-guard --service-policy "id=svc-mcp;machine=machine-1;operations=status,restart" --format jsonNormalize explicit worker or agent observation evidence. Output excerpts are
suppressed unless --allow-output-excerpt is supplied, and even then they are
bounded and secret-shaped values are rejected:
cargo run --bin ntk-control -- machine operation observe --request-id operation-restart --dispatch-id dispatch-operation-restart --machine-id machine-1 --operation service-restart --service-id svc-mcp --status passed --summary "restart completed" --output-excerpt "service restarted" --allow-output-excerpt --format jsonRender a replay report from explicit lifecycle evidence:
cargo run --bin ntk-control -- machine operation replay --request-id operation-restart --machine-id machine-1 --operation service-restart --service-id svc-mcp --approval-state approved --approval-id approval-operation-restart --dispatch-id dispatch-operation-restart --registered-machine machine-1 --ready-channel wire-guard --service-policy "id=svc-mcp;machine=machine-1;operations=status,restart" --status passed --summary "restart completed"machine operation plan, approve, dispatch-plan, observe, and replay
call the local dry-run operations contract directly. They validate target
machine, requested channel, service policy, command allowlist, approval state,
replay id, dispatch envelope, bounded observation output, replay consistency,
and secret-shaped inputs. They do not call DNS, HTTP, TCP, SSH, Docker,
Portainer, WireGuard, MCP, workers, queues, adapters, shell commands, filesystem
writers, or secret stores.
Plan a local-only task dispatch lease from explicit inventory rows:
cargo run --bin ntk-control -- tasks dispatch plan --machine "id=access-vps;status=ready;capacity=2;load=0" --worker "id=worker-access;machine=access-vps;status=ready;active=0;capacity=2" --queued-task "id=task-1;title=inspect status;workspace=/workspace"Render the same dispatch handoff as JSON:
cargo run --bin ntk-control -- tasks dispatch plan --machine "id=access-vps;status=ready;capacity=2;load=0" --worker "id=worker-access;machine=access-vps;status=ready;active=0;capacity=2" --queued-task "id=task-1;title=inspect status;workspace=/workspace" --format jsontasks dispatch plan selects a queued task, schedulable machine, and fresh
worker from caller-supplied local state, then emits a redacted lease preview
plus audit, evidence, and command-output metadata. It does not mutate the queue,
execute worker code, publish events, call adapters, or expose lease tokens.
Plan local operator alert handoff from explicit signals and routes:
cargo run --bin ntk-control -- alerts plan --signal "id=mcp-gateway-down;kind=mcp-gateway;severity=critical;subject=mcp-gateway;summary=gateway failed;observed=4000" --route "id=dashboard;kind=dashboard;target=control-dashboard;min=info" --route "id=incident;kind=incident;target=operator-incident;min=critical"Render the same alert handoff as JSON:
cargo run --bin ntk-control -- alerts plan --signal "id=worker-stale;kind=worker-freshness;severity=warning;subject=worker-access;summary=worker stale;observed=4000" --route "id=dashboard;kind=dashboard;target=control-dashboard;min=info" --format jsonalerts plan validates caller-supplied alert signals and route labels, selects
matching routes by severity, reports suppressions, and returns a dry-run
notification handoff. It does not publish webhooks, call brokers, send ChatOps
messages, read secrets, inspect services, or mutate runtime state.
Plan an MCP Gateway lifecycle action through the private route policy without starting processes or opening tunnels:
cargo run --bin ntk-control -- mcp gateway plan --operation start --machine-id copilot-vps --hostname copilot-vps --service-id mcp-gateway --wire-guard-readiness available --status configured --probe health=local-health --optional-probe tools=local-toolsPreview the explicit SSH fallback denial when WireGuard is unavailable:
cargo run --bin ntk-control -- mcp gateway plan --operation restart --machine-id copilot-vps --service-id mcp-gateway --wire-guard-readiness unavailable --wire-guard-unavailable-reason "tunnel handshake missing" --ssh-readiness availablemcp gateway plan always builds a dry-run lifecycle plan. WireGuard is the
preferred required route by default, SSH fallback is denied unless
--allow-ssh-fallback is supplied, and unknown readiness denies required
routes. The command does not call MCP, start or stop processes, create tunnels,
execute SSH, mutate WireGuard, call Docker, read files, or resolve secrets.
Plan a generic service action through the control server boundary:
cargo run --bin ntk-control -- services action plan --service-id access-control --service-name "Access Control" --service-kind model-control-api --operation status --command-id service.statusPreview a mutating restart with approval, a fresh worker, and a non-dry-run request. This still only creates the plan and does not execute the restart:
cargo run --bin ntk-control -- services action plan --service-id access-control --service-name "Access Control" --service-kind model-control-api --operation restart --command-id service.restart --approved --execute --worker-readyRender the service-action plan as the existing CommandOutputEnvelope JSON
contract:
cargo run --bin ntk-control -- services action plan --service-id access-control --operation collect-evidence --command-id service.collect-evidence --format jsonservices action plan builds an in-memory machine, service, worker,
allowlist, audit, evidence, and queue view from explicit arguments, then calls
the generic control server planner. Mutating operations require the service
operation allowlist, approval, non-dry-run intent, and --worker-ready. The
command does not call DNS, HTTPS, TCP, SSH, Docker, Portainer, WireGuard,
service runtimes, shell commands, broker APIs, filesystem writers, or secret
stores.
Plan a local-only Control event publish batch before any broker adapter runs:
cargo run --bin ntk-control -- events publish plan --target-label rabbitmq-control --event evt-1=service-action-planned --event evt-2=worker-heartbeat --max-events 1Render the same event batch plan for automation:
cargo run --bin ntk-control -- events publish plan --target-label rabbitmq-control --event evt-1=service-action-planned --format jsonevents publish plan builds an in-memory pending outbox from explicit
event_id=kind declarations, selects up to --max-events, and reports whether
more pending events remain. It does not call RabbitMQ or any broker, read or
write files, call HTTP, DNS, SSH, Docker, mutate services, or resolve secrets.
Plan the current Access smoke profile without running live probes:
cargo run --bin ntk-control -- smoke plan --profile access --scope fullRender JSON machine output for a scoped manual check:
cargo run --bin ntk-control -- smoke plan --profile access --scope observability --format jsonUse strict planning when a missing required probe should fail the dry run:
cargo run --bin ntk-control -- smoke plan --profile access --scope full --strictEvaluate an observed smoke run from explicit probe outcomes:
cargo run --bin ntk-control -- smoke run --profile access --scope observability --observation runtime=passed --observation ssh=passed --observation seq_https=passed --observation seq_health=passed --observation otel_ports_closed=passed --observation observability_containers=passedCollect live network observations for selected probes without shelling out:
cargo run --bin ntk-control -- smoke run --profile access --scope observability --observation runtime=passed --observation ssh=passed --observation seq_https=passed --observation otel_ports_closed=passed --observation observability_containers=passed --http seq_health=127.0.0.1:5341/health --timeout-ms 2000Validate SSH reachability by reading only the server banner:
cargo run --bin ntk-control -- smoke run --profile access --scope observability --observation runtime=passed --ssh-banner ssh=127.0.0.1:22 --observation seq_https=passed --observation seq_health=passed --observation otel_ports_closed=passed --observation observability_containers=passed --timeout-ms 2000Validate an authenticated local HTTP boundary by expecting a specific status:
cargo run --bin ntk-control -- smoke run --profile access --scope control --observation runtime=passed --observation ssh=passed --observation control_https=passed --observation control_container=passed --http-status control_authenticated_api=401,127.0.0.1:3000/api/servers --timeout-ms 2000Validate Access Control by logging in with credentials supplied through the
environment and then checking an authenticated route. The default env names are
NTK_ACCESS_CONTROL_USERNAME and NTK_ACCESS_CONTROL_PASSWORD; override the
names with --access-control-auth-username-env and
--access-control-auth-password-env when needed.
cargo run --bin ntk-control -- smoke run --profile access --scope control --observation runtime=passed --observation ssh=passed --https control_https=control.access.nettoolskit.io:443/ --observation control_container=passed --access-control-auth --timeout-ms 5000Validate a public HTTPS/TLS route directly with certificate verification:
cargo run --bin ntk-control -- smoke run --profile access --scope control --observation runtime=passed --observation ssh=passed --observation control_container=passed --https control_https=control.access.nettoolskit.io:443/ --https-status control_authenticated_api=401,control.access.nettoolskit.io:443/api/servers --timeout-ms 5000Collect fixed read-only Access runtime observations over SSH:
cargo run --bin ntk-control -- smoke run --profile access --scope remote --observation runtime=passed --ssh-banner ssh=access-vps.example:22 --tcp rustdesk_tcp_21115=rustdesk.access.nettoolskit.io:21115 --tcp rustdesk_tcp_21116=rustdesk.access.nettoolskit.io:21116 --tcp rustdesk_tcp_21117=rustdesk.access.nettoolskit.io:21117 --negative-https rustdesk_web_negative=rustdesk.access.nettoolskit.io:443/ --https wireguard_https=wireguard.access.nettoolskit.io:443/ --access-runtime-ssh-target [email protected] --access-runtime-compose-project nettoolskit-access --timeout-ms 5000smoke run consumes explicit observations and can now collect direct live
network observations for DNS resolution, TCP reachability, closed public port
checks, SSH banner detection, plain HTTP health endpoints, exact expected HTTP
status checks for local authenticated guards, HTTPS/TLS route status checks
with public root certificate verification, authenticated Access Control login
and route validation through --access-control-auth, and negative HTTPS route
checks for surfaces that must not expose a web UI. Missing observations for
selected, configured probes are failures, which keeps partial live smoke
commands honest. Live network probes use the Rust standard library plus Rust
TLS primitives; no shell, SSH authentication, remote command, Docker,
Portainer, WireGuard, external HTTP client, file writer, or secret store is
called. The authenticated Access Control probe defaults to
control.access.nettoolskit.io:443, /api/login, /api/servers, and
expected status 200; it reads credential values from env vars, keeps cookies
or bearer tokens only in memory, and emits only status summaries. Access
runtime SSH probes are explicit and read-only: the CLI invokes the local ssh
binary only when --access-runtime-ssh-target is supplied, runs predeclared
Access runtime inspections, and emits bounded observations without serializing
raw command output or secret material. For edge and observability scopes, those
fixed inspections also verify that NPM admin, legacy proxy, Traefik metrics,
and OTEL collector ports do not have non-loopback listeners on the remote host.
Edge runtime inspections also check the Traefik loopback /ping and
/metrics endpoints, and backup inspections include the Traefik ACME volume
marker in the dry-run evidence.
Plan a RustDesk local client config import without writing files:
cargo run --bin ntk-control -- rustdesk config import plan --config-root .\.temp\rustdesk-config-previewApply the same import to the current user's RustDesk config directory, creating
*.bak backups for existing files before mutation:
cargo run --bin ntk-control -- rustdesk config import applyInject optional RustDesk server values without printing them in the report:
cargo run --bin ntk-control -- rustdesk config import plan `
--rendezvous-server rustdesk.access.nettoolskit.io `
--relay-server rustdesk.access.nettoolskit.io `
--server-key YOUR_PUBLIC_KEY `
--format jsonrustdesk config import updates only RustDesk2.toml and
RustDesk_default.toml under the selected config directory. The built-in
defaults are product-neutral; callers can pass --runtime-template and
--display-template when a repository owns stricter tuning files. Plan mode is
read-only. Apply mode writes local files only, with backups for existing files,
and never calls Access, SSH, Docker, Portainer, Bitwarden, DNS, RustDesk
services, or secret stores.
The CLI currently performs local policy evaluation, planning, observed-result evaluation, explicit live DNS/TCP/plain-HTTP/HTTPS smoke checks, and explicit local RustDesk config file import. It does not call SSH authentication, remote command execution, Docker, Portainer, WireGuard, Seq, Traefik, shell commands, service runtimes, or secret stores.
Service Manifest
nettoolskit.manifest.json declares the control-plane capabilities, adapter
families, optional ingress secrets, and evidence artifact kinds. It is generated
from nettoolskit-contracts and should stay aligned with the Rust catalog.
River CI
This repository follows the Access local-first CI/CD strategy: GitHub remains the source of truth, while GitRiver/River runs expensive pull-request quality gates from metadata-only workflows.
River quality gates live in .gitriver/workflows/control-quality.yml and
execute the mutable source-owned scripts under scripts/ci/river/ after
cloning this repository from GitHub. The workflow also clones nettoolskit-rust
as a sibling directory because this crate uses path dependencies for shared CLI
and contract crates.
The current River status context is:
river/control-rust-quality
GitHub-hosted checks for this repository should stay limited to lightweight governance or release/deploy handoff work. Rust formatting, tests, clippy, package checks, and vulnerability audits belong in River.
The GitHub Actions workflow at .github/workflows/metadata-guard.yml is a
metadata-only guard. It verifies that GitHub Actions does not grow heavy Rust
quality work, that River keeps publishing commit status and failure issues, and
that shallow changed-surface detection still covers runtime changes even when a
PR's latest commit is documentation-only.
Repository Layout
This repository is a Rust workspace. The root package owns the ntk-control
CLI, while reusable control-plane contracts and planners live in
crates/core/src/<responsibility>/mod.rs. Mirror those responsibilities in
tests/<responsibility>/.
Cargo output is pinned by .cargo/config.toml to .build/target. Generated
validation or publication artifacts belong under .deployment/artifacts and
must not be committed.
Non-Goals
- No concrete process execution adapter yet.
- No GitHub-hosted heavy CI/CD workflows.
- No duplicated DTOs from
nettoolskit-contracts. - No direct dependency on
nettoolskit-copilot. - No live RustDesk service probing or remote workstation management.
Validation
cargo fmt --check
cargo audit --deny warnings
cargo test
cargo clippy --all-targets -- -D warnings
cargo buildDET local effectiveness use gate
Control keeps DET distribution disabled until DET produces a local effectiveness summary backed by real host-reported or provider-reported metrics, the summary decision is use_det, and the Assurance redaction/safety gate passes.
First-wave distribution channels controlled by this policy are GitHub Release binaries, npm, and Docker. Cargo and winget are intentionally out of scope for the current DET distribution plan.
See docs/det-local-effectiveness-use-gate.md,
docs/runbooks/det-local-effectiveness-use-gate.md, and
tests/fixtures/det-local-effectiveness/control-use-gate.pending.json for the
current blocked policy state and review workflow.
DET local effectiveness gate check
evaluate_det_effectiveness_gate consumes already-produced DET, Analytics, Assurance, and DevOps outcomes and returns a Control policy decision for first-wave DET distribution. The gate allows distribution only when Analytics reports use_det_candidate, metrics are host/provider distribution-grade, readinessDecision is use_det, the DET readiness/economic/first-use/Harness proof bundle fields pass, Assurance passed redaction/safety, and DevOps allows publication.
When DET emits a local effectiveness package, Control consumes its
use_det/hold/blocked recommendation through
DetLocalPackageRecommendation. use_det can advance only when the remaining
Analytics, Assurance, and DevOps gates also pass; hold and blocked remain
distribution blockers.
See docs/det-local-package-control-contract.md.
The gate does not run DET, benchmarks, Analytics, Assurance, Docker, npm, GitHub Release publication, shell commands, or CI/CD workflows.
npm and npx
This repository exposes the ntk-control command through the @nettoolskit/control npm package for local installation and npx execution.
npm install -g @nettoolskit/control
ntk-control --help
npx @nettoolskit/control --helpThe npm wrapper executes a native ntk-control binary from npm/native/ when release packaging stages one. For development or private release validation, set NTK_CONTROL_BINARY to an already built local binary. Use npm run stage:native -- <path-to-binary> before packaging a native tarball.
