Per Phase 1 audit at cowork/docs-overhaul-phase-1-audit-2026-05-04/
and the section-by-section plan in testing-guide-tumor.md.
testing-guide.md was 30% of all docs/ content (8268 lines) but was
integration test code written in markdown, not operator documentation.
The audit's tumor analysis disposed of every Part:
- ~65% DELETE (test cases that already exist in code)
- ~22% MOVE to inline test code
- ~8% KEEP-COMPRESSED into focused operator-runbook docs
- Title + contents + release sign-off ~5% KEEP
This commit ships the KEEP-COMPRESSED dispersal:
docs/contributor/qa-prerequisites.md (NEW, ~120 lines):
From testing-guide.md "Prerequisites" section. Stack boot procedure,
demo data baseline, reference IDs operators reuse across QA docs.
docs/contributor/gui-qa-checklist.md (NEW, ~105 lines):
From testing-guide.md "Part 35: GUI Testing". Manual GUI verification
pass for release sign-off. 25-row table covering every dashboard page.
docs/contributor/release-sign-off.md (NEW, ~130 lines):
From testing-guide.md "Release Sign-Off" section (originally 1009
lines of per-test detail tables). Compressed to a release-day
checklist organized by gate category: code state, automated gates,
manual QA passes, release artefact verification, branch protection,
post-release.
docs/operator/performance-baselines.md (NEW, ~100 lines):
From testing-guide.md "Part 39: Performance Spot Checks". Four
operator-runnable benchmarks (API request handling, inventory list
pagination, scheduler tick, bulk revoke) with baseline numbers and
when-to-re-baseline guidance.
docs/operator/helm-deployment.md (NEW, ~120 lines):
From testing-guide.md "Part 52: Helm Chart Deployment". Operator
runbook for the bundled deploy/helm/certctl/ chart: prereqs,
install, four cert-source patterns, verify, upgrade, troubleshooting.
docs/reference/cli.md (NEW, ~120 lines):
From testing-guide.md "Part 28: CLI Tool". certctl-cli command
reference with command-group breakdown, common workflows
(list/filter, renew, revoke, bulk import, EST enrollment, status),
output formats, CI/CD integration patterns.
docs/README.md navigation index updated to include the 6 new docs:
Reference section gains: cli.md, release-verification.md (was added
in Phase 13)
Operator section gains: helm-deployment.md, performance-baselines.md
Contributor section gains: qa-prerequisites.md, gui-qa-checklist.md,
release-sign-off.md
docs/testing-guide.md deleted. Git history preserves the 8268 lines —
if any specific test case is found missing from inline test code or
the destination docs during future work, lift from `git show
HEAD~1:docs/testing-guide.md`.
Net: docs/ total line count drops by ~7700 lines (28%), from 26,369
to 18,742. testing-guide.md was the single largest doc; pruning it is
the single biggest content-edit win of the entire restructure.
Phase 5 is the last major content phase. Remaining: Phase 4 follow-on
(per-connector page extractions from reference/connectors/index.md),
Phase 15 (WHAT/HOW/WHY remediation), Phase 16 (final acceptance gate).
4.3 KiB
certctl CLI
Last reviewed: 2026-05-05
certctl-cli is the command-line interface to certctl. It wraps the REST API as terminal commands so operators and CI/CD pipelines can drive certctl without writing curl invocations.
Install
go install github.com/certctl-io/certctl/cmd/cli@latest
The binary lands at $GOBIN/cli (or $HOME/go/bin/cli if GOBIN is unset). Rename to certctl-cli if you prefer.
Configure
The CLI reads three environment variables:
export CERTCTL_SERVER_URL=https://localhost:8443
export CERTCTL_API_KEY=your-api-key
export CERTCTL_SERVER_CA_BUNDLE_PATH=/path/to/ca.crt
Or pass them per-invocation:
certctl-cli --server https://localhost:8443 --api-key your-key --ca-bundle ca.crt certs list
For local development against a self-signed bootstrap cert, --insecure skips TLS verification. Never set this in production.
Command groups
The CLI is organized by resource:
certctl-cli certs [list|get|renew|revoke]
certctl-cli agents [list|get]
certctl-cli jobs [list|get|cancel]
certctl-cli import [bulk PEM import]
certctl-cli est [enroll|reenroll]
certctl-cli status [server health + summary stats]
certctl-cli version [CLI + server version]
Common workflows
List + filter certificates
# All certs
certctl-cli certs list
# Filter by environment
certctl-cli certs list --env production
# JSON output (default is table)
certctl-cli certs list --format json
# Sort + paginate
certctl-cli certs list --sort -expires_at --limit 50
# Time-range filter (RFC 3339)
certctl-cli certs list --expires-before 2026-06-01T00:00:00Z
# Sparse fields — only return the columns you need
certctl-cli certs list --fields id,common_name,expires_at,status
Trigger renewal
certctl-cli certs renew mc-api-prod
# Returns the job id; track with: certctl-cli jobs get <job-id>
Revoke
# Single revoke
certctl-cli certs revoke mc-api-prod --reason keyCompromise
# Bulk revoke by filter
certctl-cli certs revoke --profile prof-deprecated --reason superseded
certctl-cli certs revoke --team t-payments --reason cessationOfOperation
certctl-cli certs revoke --issuer iss-old-vault --reason cACompromise
Reason codes are the canonical RFC 5280 §5.3.1 set: unspecified, keyCompromise, cACompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold, removeFromCRL, privilegeWithdrawn, aACompromise. Anything else returns an error.
Bulk import
# Import a directory of PEMs
certctl-cli import /etc/letsencrypt/live/
# Import a single concatenated bundle
certctl-cli import certs.pem
Each cert lands in the inventory as Unmanaged (per the discovery model). Triage from the dashboard or via certctl-cli certs claim <id> once you've decided to actively manage it.
EST enrollment
# Enroll a new device cert via EST simpleenroll
certctl-cli est enroll --csr device.csr --output device.crt
# Re-enroll (renew) an existing device cert
certctl-cli est reenroll --csr device.csr --client-cert device.crt --client-key device.key
Server status
certctl-cli status
# Health: ok
# Total certificates: 145
# Expiring (30d): 12
# Active jobs: 3
# Pending renewals: 8
Output formats
--format table(default) — human-readable terminal output--format json— JSON for piping intojq, scripts, dashboards
The CLI is built with Go's standard library only — no external dependencies. The binary is small (~10MB) and statically linked.
Wiring into CI/CD
Common pattern: a CI step that issues a cert from your internal CA, deploys it via certctl, and verifies the deploy:
certctl-cli certs renew mc-api-prod --wait
certctl-cli jobs get $(certctl-cli certs renew mc-api-prod --json | jq -r '.job_id') --wait
certctl-cli certs get mc-api-prod --json | jq -r '.expires_at'
The --wait flag blocks until the job reaches a terminal state (Completed / Failed / Cancelled), which is what CI scripts actually need.
Related docs
docs/reference/api.md— the OpenAPI 3.1 spec the CLI wrapsdocs/reference/mcp.md— the MCP server that exposes the same surface to AI assistantsdocs/contributor/qa-prerequisites.md— local environment setup before the CLI can talk to a server