Release, pin & license-review a CLI tool
AdminIn the desktop edition, the CLI command tool runs external command-line programs. This how-to is for operators: it covers the approval flow in operation, version pinning (the binary allowlist), and the license/redistribution review gate every bundled CLI must pass before it ships. For the end-user overview and the customer-readable guarantee statement, see → Command-line tools (CLI) in the assistant — overview & limits. For where configurable tools fit, see Configurable tools — overview.
The approval flow in operation
Section titled “The approval flow in operation”A state-changing or network-reaching command never starts automatically:
- The assistant builds a manifest — the program plus its arguments as a fixed list (
argv), never a free shell line. - Before execution, the HITL approval dialog appears: it shows the exact
argvand a dry run (what would happen) before anything runs. - Execution happens only after human approval. Reading calls are exempt; anything writing or network-reaching needs approval.
- Every execution produces an audit record — the run is logged and traceable.
This human approval, together with credential-scoping, is the load-bearing security boundary (see the guarantee boundary below), not the OS sandbox.
Enable version pinning
Section titled “Enable version pinning”Raw CLI output is version-dependent. To ensure only a vetted, exact version launches, there is a binary allowlist with checksum verification.
- Default without a registry = unpinned. With no registry configured, the binary launches as-is (still under sandbox, default-deny egress, credential-scoping and HITL). This is logged once. It preserves the behaviour of existing deployments.
- Turn pinning on: point
Cli:BinaryRegistryPathat acli-binaries.json. The strict registry then loads at startup. - Fail-loud: a configured-but-missing or malformed registry file makes the application fail hard at startup — an allowlist must not silently degrade to “allow all”.
cli-binaries.json format
Section titled “cli-binaries.json format”Per binary: name → version → per platform path + SHA-256.
{ "binaries": [ { "name": "git", "version": "2.45.1", "platforms": { "osx-arm64": { "path": "/Applications/CompanyWizard.app/Contents/Resources/bin/git", "sha256": "ab12…" }, "win-x64": { "path": "C:\\Program Files\\CompanyWizard\\bin\\git.exe", "sha256": "ef56…" } } } ]}namematchesmanifest.binaryexactly (case-sensitive).- Platform keys are .NET RID short forms:
osx-arm64,osx-x64,win-x64,win-arm64,linux-x64, … - Generate
sha256as hex: macOS/Linuxshasum -a 256 <file>, WindowsGet-FileHash <file> -Algorithm SHA256.
Before any launch the executor resolves manifest.binary + manifest.version against the registry and verifies the on-disk file for the current OS/arch. Only a binary that is registered, pinned to the version, present for this platform and hash-matching launches — via the registry-resolved absolute path, never the raw manifest value. Every drift (not registered, missing/mismatched version, no platform entry, file missing, hash mismatch) is a fail-closed reject — before the sandbox, the approval dialog or secret resolution are reached.
Bundling per OS
Section titled “Bundling per OS”The pinned binaries ship inside the Photino package so paths and hashes are known at build time; the registry file is generated as a build step that hashes the bundled binaries.
- macOS (.pkg/.app): binaries under
CompanyWizard.app/Contents/Resources/bin/. Generatecli-binaries.jsoninmacos/build-macos.shafter stagingResources/bin/and before signing. - Windows (Velopack/vpk): binaries under
bin\in the package root; generate in the vpk pack step. - Cross-OS availability: not every CLI ships for every platform. A registration lacking the current platform is a fail-closed reject (no fallback) — decide per binary which platforms to bundle and document the gaps.
License & redistribution gate
Section titled “License & redistribution gate”Bundling a third-party CLI inside the package is redistribution, so each one needs license and patent clearance before it ships. Currently bundled: none. The unpinned default ships zero binaries; concrete CLI selection is a product/sales decision. Before a binary is added to the registry and to the inventory table, this sign-off applies:
- Identify the license from the upstream release (not guessed); record the SPDX id.
- Redistribution cleared for our bundling form (binary, inside a signed installer):
- Permissive (MIT, BSD-2/3, Apache-2.0, ISC) → low risk; Apache-2.0 also grants a patent license → preferred where there is a choice.
- Weak copyleft (MPL-2.0, LGPL) → allowed, but file-/library-scoped obligations; keep the binary unmodified and carry the upstream notices.
- Strong copyleft (GPL-2.0/3.0, AGPL) → flag. Bundling triggers source-offer obligations; AGPL adds network-use obligations. Requires explicit legal sign-off or a different tool — do not bundle on a maintainer’s say-so.
- Check patent exposure — prefer permissive/Apache-2.0 with an explicit patent grant; note known encumbrances (codecs, crypto-export).
- Carry notices — bundle upstream LICENSE/NOTICE in the package.
- Record the sign-off (✅ + who/when) before the registry pin lands.
A binary that reaches cli-binaries.json without a ✅ row is a release blocker.
Guarantee boundary (brief)
Section titled “Guarantee boundary (brief)”Containment is best-effort plus egress control, not VM isolation; the core boundary is credential-scoping + HITL approval. The full, customer-readable statement lives in the end-user overview → Command-line tools (CLI) in the assistant — overview & limits.
Related
Section titled “Related”- Configurable tools — overview — where self-configured tools fit.
- Set up a folder as a tool (desktop) — the same sandbox/containment story.
- Command-line tools (CLI) — overview & limits — end-user view and guarantee statement.