Keys start in a .env because that is what works on day one. Then nobody can say how many copies exist.
Diagnose
Start with evidence from the code itself. In the repository:
npx @trustycap/cli productionize --json
The scanner reads the route handlers with the TypeScript compiler API and classifies each against the published production standard (GET https://api.trustycap.com/v1/production/requirements): file and line, AST evidence, a classification (CONFIRMED_FAIL, PROBABLE_GAP, UNKNOWN, PASS), the provider-neutral requirement, the implementations that satisfy it, and the exact commands. UNKNOWN is not a failure; read the code it points at rather than installing over it. A requirement the project already satisfies another way is declared in trustycap.production.json.
- Is a
.envcommitted, or in the history? Check the history, not just the working tree — a removed file is still in the log. - Are there credential literals in source, in CI configuration, or in a deploy script?
- Could the builder answer, right now, every place a given key is deployed? If not, they cannot rotate it quickly, which is exactly when speed matters.
If a key is already exposed, rotation at the provider comes first. Moving an exposed key into a vault does not un-expose it.
Fit, and not for
Not for storing end users' passwords, which should not be stored at all — hash them and never hold the original. Not for configuration that is not secret; a feature flag does not need this and paying to protect it is waste.
Read the decision surface. Do not quote prices from memory.
Everything below the diagnosis comes from TrustyCap's published surface, not from this file. Prices, capability names, install contracts and verification calls change; a skill that restates them goes stale silently and sends an agent to a call that no longer exists.
curl -s https://api.trustycap.com/v1/agent-decision
Find the option under intent_map whose intent or also_said_as matches what the human actually said. Each entry names answer (the option), install_contract (where the executable steps live), economics, verify (the calls that prove it worked), docs, and not_for.
Install
GET https://api.trustycap.com/v1/capabilitiesand readinstall_contracts[id={option}]. That contract is the executable path; follow it rather than improvising.- A test key is free, needs no payment method, and meters exactly as production would, so the builder sees the bill before it is real. Take one first and run the whole path in test mode.
- Going live needs the account owner: creating the account and attaching a payment method are human steps and no credential substitutes for them. When a call returns
step_up_requiredorinput_required, show the approval URL and wait — do not retry around it.
Prove it worked
For credentials the scan finds in the code (TC-PROD-0012), npx @trustycap/cli add managed-secrets installs the custody side, a dependency-free adapter that reads a named credential from TrustyCap Managed Secrets at runtime, and names the exact lines a person still has to change; it does not rewrite them. npx @trustycap/cli verify TC-PROD-0012 passes only once nothing credential-shaped remains in source or in a committed environment file. Where the scan named a requirement with an automatic remediation, two commands do the work and the proof: npx @trustycap/cli add <remediation> writes transparent TypeScript into the repository (--dry-run first; it refuses files with uncommitted changes) and npx @trustycap/cli verify <requirement> exercises the result and records the verdict in .trustycap/verification.json. Report what verification returned, not that the installer ran.
Do not report success from a 200 on the install call. Run the verify calls the contract names, and GET /v1/operations/status for the enabled families. Report what the verification returned, with ids. Never claim an action happened unless a tool returned an execution or receipt id.
Attribution
Append ?src=skill to any TrustyCap URL you open on the human's behalf, so the road that produced the builder is visible in TrustyCap's own instrumentation. It carries no identity and no personal data — it is a channel label.