Discern, then decide — before you sign. Local key-material hygiene and readiness checks for humans and agents.
decernor inspects local signing and authentication material — GPG, minisign, and
SSH keys, revocation certificates, public counterparts, and checksum manifests — and
decides what is plaintext, what is protected, what is public, and what to remove,
retain, or inspect. It reads the state, never the secret.
Name note:
decernor(from Latin decernere, "to decide / determine / decree"; root cernere, "to sift, distinguish, discern"). Pronounced deh-SUR-nor. SeeNAMING.mdfor the decision record.
This tool helps humans and AI agents inspect local key-material hygiene without directly reading, copying, or disclosing private key contents.
Modern release and automation workflows depend on local signing and authentication assets: GPG keys, minisign keys, SSH keys, revocation certificates, public counterparts, and checksum/signature manifests. Those assets are powerful and easy to mishandle. A human operator may need to know whether a machine is clean enough, whether a secure archive contains the right encrypted materials, or whether an automation session can proceed without exposing secrets to a remote agent.
The core idea is simple:
Trusted local code inspects sensitive local state and emits structured findings. Humans and agents consume the findings, not the private key material.
The tool does not make a software-held key magically safe. It distinguishes between plaintext private material, encrypted/passphrase-protected material, public material, operationally sensitive artifacts such as revocation certificates, and copied keyring internals. It reports whether something should be removed, retained with controls, or inspected manually.
This is a general OSS trust utility, homed in the 3leaps collection org.
It is adjacent to tools like:
sfetch: verifies downloaded release artifacts before execution.shellsentry: inspects shell scripts before execution.decernor(this tool): inspects local key-material state before humans or agents act on it.
AI-assisted workflows are an important use case: agents can use this tool to avoid asking users to paste, upload, or describe private key files in a live session. Decernor uses Fulmen microtool foundations for config, schema validation, structured logging, identity, and release ceremony patterns.
- Release engineers preparing signed OSS releases.
- Operators creating or archiving GPG, minisign, and SSH assets.
- Less experienced users who need plain guidance on whether local key files are plaintext, encrypted, or public-only.
- AI agents that need to reason about key readiness without reading key contents.
- Enterprise teams that need policy-shaped output for local machine cleansing, secure handoff, and release signing readiness.
scan answers:
What risky or sensitive key material is present here?
Examples:
go run ./cmd/decernor scan /path/to/artifacts
go run ./cmd/decernor scan /path/to/artifacts --format json
go run ./cmd/decernor scan /path/to/artifacts --profile workstation
go run ./cmd/decernor scan /path/to/artifacts --fail-on warn
go run ./cmd/decernor scan /path/to/artifacts --allow-protected-secret-keys
go run ./cmd/decernor --log-level info scan /path/to/artifacts --format jsonScan reports are written to stdout. Operational logs are written to stderr when enabled with --log-level info, so CI can safely pipe JSON reports without log contamination.
guardread answers:
Can this one file be read to stdout without first exposing supported key-material bytes?
Example:
go run ./cmd/decernor guardread ./notes.txtThe command accepts one named regular file. It rejects symlinks, directories, special files, oversized files, binary/ambiguous input, and supported key-material detections before writing any file byte to stdout. On pass, stdout is the file content only. On refusal, stdout is empty and sanitized diagnostics are written to stderr with exit code 3. Input and usage errors exit 2.
guardread is not a prompt-injection filter or a general content-safety system.
It protects the supported detector classes Decernor can recognize; arbitrary
prose still needs whatever higher-level review applies to that workflow.
readiness answers:
Do I have enough usable, protected material for a capability?
Capabilities use a provider plus verb model:
gpg/signgpg/encryptminisign/signssh/auth
The current cut includes schema-backed config validation:
go run ./cmd/decernor readiness validate-config examples/github-org-bootstrap.readiness.jsonfingerprint answers:
What safe public identity fingerprints can be emitted for this key material?
Examples:
go run ./cmd/decernor fingerprint /path/to/artifacts
go run ./cmd/decernor fp /path/to/artifacts --kind ssh,minisign
go run ./cmd/decernor fingerprint /path/to/artifacts --format json
go run ./cmd/decernor fingerprint /path/to/artifacts --fail-on-empty
go run ./cmd/decernor fingerprint ./release.gpg.asc --class public --kind gpg \
--format json --path-mode none --gpg-role primaryThe default format is newline-delimited JSON. --format json emits an array of
the same records. Fingerprint records are written to stdout; diagnostics remain on
stderr. Output paths default to --path-mode relative, which emits paths relative
to the input root. Use --path-mode hash for artifacts leaving a repository
boundary, or --path-mode none to omit path metadata. The command does not
traverse symlinks or consult ambient keyrings, agents, home directories, hardware
tokens, or the network.
Records use schema_version:"v0" and the schema in
schemas/fingerprint-record.v0.schema.json. Config files use
schemas/fingerprint-config.v0.schema.json.
For minisign public keys, fingerprint emits both the native
minisign-key-id-v1 identifier and the collision-resistant
minisign-public-blob-sha256-v1 fingerprint (lowercase 64-hex in the
record). Use the public-blob SHA-256 field for committed trust anchors; the
key ID remains useful for display and operator correlation. A GPG public
export uses --gpg-role primary when the caller needs exactly one primary
fingerprint.
Future readiness checks should support two levels:
- Static readiness: key material exists, is not plaintext, has expected public counterpart, revocation certificate is present where required.
- Proof readiness: local-only proof such as sign-and-verify, encrypt-and-decrypt, or derive public key. Proof mode may prompt for passphrases, but must not transmit key material.
Findings are structured for both humans and automation.
Fields include:
code: stable finding identifier, suitable for runbooks and allow/deny policy.priority: remediation priority fromP0toP5.rank: numeric sort rank derived from priority.classification: artifact category, such asprotected-secret,ssh-private-key, orminisign-secret.severity: current policy severity:info,warn, orunsafe.retention:allowed,retain-with-controls,inspect-manually, orremove.exposure:public,sensitive,secret, orunknown.sensitivity: 3 Leaps classifier value embedded in the scanner model.confidence:high,medium, orlow.evidence: short explanation without printing private material.recommendation: next action.
Example:
{
"code": "MINISIGN-ENCRYPTED-SECRET",
"priority": "P3",
"rank": 300,
"classification": "minisign-secret",
"severity": "warn",
"retention": "retain-with-controls",
"exposure": "secret",
"sensitivity": "5-privileged",
"confidence": "high",
"evidence": "encrypted minisign secret material detected",
"recommendation": "Potentially retainable with strong passphrase and local controls; keep out of artifact bundles unless policy allows it."
}- ASCII armor is encoding, not protection.
- Public keys and signatures are not private, but may still be operationally relevant.
- Passphrase-protected software keys are sensitive and potentially retainable with controls.
- Plaintext private keys are unsafe.
- Copied keyring internals are suspicious outside their expected home.
- Revocation certificates are operationally sensitive and should be archived intentionally.
- Hardware-backed keys should be preferred or required where policy calls for that.
- The tool should not decrypt user data, collect passphrases, or print private key material.
Decernor dogfoods the same trust practices it encourages. It fingerprints its own release-signing publics and pins those values into the signed set. The assets this tool scans are the same class of assets used to sign its releases.
A cut is two phases:
- Tag
vX.Y.Z. CI packages unsigned archives and opens a GitHub release. - On an operator host,
make releasedownloads those archives, stages committed fingerprint pins and notes, checksums, signs the SUMS (minisign required; PGP optional), exports publics, verifies, and uploads onto the same release.
The signed payload is archives + notes +
expected-fingerprints.{txt,ndjson}. Exported .pub / .asc files ride
beside it; they do not vouch for themselves. Pins are generated by
decernor fingerprint on those exported publics
(make release-insert-anchors), never hand-typed. Bindings are
environment-variable identifiers only.
Reviewers:
- Inspect the source, including
keys/expected-fingerprints.txt. - Download archives, signed SUMS, exported publics, and the staged pin pair.
- Verify the signatures over the checksum manifests.
- Verify archive checksums. The pin files must be members of SUMS.
- Run
decernor fingerprinton the exported publics and compare to the pin file (see below). - Run the tool locally and consume structured findings, not key files.
Layout and signed-set membership:
docs/decisions/PDR-0001-committed-signing-anchors.md.
Inserter: keys/README.md.
Consume fingerprints, not secrets. Per-cut commands live in
docs/releases/v0.1.5.md.
Download the release assets (archives, signed SUMS, exported publics, staged pin pair). Verify SUMS signatures, then:
decernor fingerprint decernor-release-signing-key.asc \
--class public --kind gpg --format json --path-mode none --gpg-role primary
decernor fingerprint decernor-minisign.pub \
--class public --kind minisign --format json --path-mode noneThe GPG primary fingerprint and the minisign public-blob SHA-256 must
match the gpg and minisign lines in expected-fingerprints.txt.
Never hand-type hex into notes or a README.
go build ./...
make build
./bin/decernor versionInstall Decernor from the 3 Leaps package repositories:
brew install 3leaps/tap/decernorscoop bucket add 3leaps https://github.com/3leaps/scoop-bucket
scoop install decernorPackage managers are a convenience distribution path. For release provenance, continue to verify the signed GitHub release assets and fingerprint pins.
Readiness configs describe what capabilities an asset set must support.
The schema is in schemas/readiness-config.v0.schema.json. Example configs live in examples/.
Example capability:
{
"id": "gpg-release-sign",
"provider": "gpg",
"verb": "sign",
"accepted_material": ["protected-secret-key", "hardware-backed-key"],
"require_public_counterpart": true,
"require_revocation_certificate": true,
"static_checks": [
"material-present",
"not-plaintext",
"public-counterpart",
"revocation-present"
],
"proof_checks": ["sign-and-verify"]
}decernor was selected to suggest local trust, key-material hygiene, and readiness
before signing/authentication — without sounding like malware, spyware, a password
manager, a generic cleaner, or a destructive wipe tool, and without implying the tool
stores secrets or guarantees safety.
- Etymology: Latin decernere — "to decide, determine, decree, resolve" — on the root cernere ("to sift, distinguish, discern"). The tool discerns key-material state, then decides the verdict: remove, retain-with-controls, inspect, or allowed.
- Tagline shapes:
- Discern, then decide — before you sign. (CLI / repo subtitle)
- Know what's safe to keep — without reading the secret. (landing)
- ASCII armor is encoding, not protection. Decernor tells the difference. (technical overview)
- Surfaces: binary
decernor, config path~/.config/3leaps/decernor.yaml, env prefixDECERNOR_, default configdecernor.yaml. Finding codes and readiness-config shapes are name-agnostic and unchanged.
Full decision record, surfaces grid, and the considered-but-passed runner-up (cernor)
are in NAMING.md.
The repository avoids committed real keys and avoids full static secret-key fixtures. Tests generate small synthetic files at runtime and mock packet output so downstream secret scanners have less static material to flag.
Decernor was initially built from the public Fulmen microtool forge baseline forge-microtool-gimlet, then adapted as a 3 Leaps OSS tool.
This project is licensed under the MIT License. See LICENSE.