Commands
who (alias: preview-ownership)
For each selected secret, decide: mine, someone else's, or unknown. Hits only read-only endpoints. Never mutates anything.
Why this exists
In a shared Vercel team, a CLERK_SECRET_KEY in
project-x might belong to Cueva's Clerk account, not
yours. Rotating it with your PLAPI key would fail, or
worse, succeed against a Clerk instance you don't own and charge
you for billing. who catches that before rotation.
Usage
$ rotate-cli who [selector...] [flags] Selecting secrets
| Flag | Meaning |
|---|---|
--from-scan | Use cached rotate-cli scan output (recommended). |
--provider <name> | Filter by adapter (e.g. clerk). |
--tag <name> | Filter by tag (e.g. non-sensitive from scan). |
--scan-max-age 15m | Re-scan if cache older than this. |
--fresh | Ignore cache, force a fresh scan. |
Verdicts
| Verdict | Glyph | What it means |
|---|---|---|
| self | ✓ | Evidence the secret belongs to the authenticated admin. Safe to rotate. |
| other | ✗ | Evidence it belongs to another account. Rotating would fail or charge the wrong person. |
| unknown | ? | Adapter couldn't decide. Usually provider API limitation or missing sibling hint. |
| no-check | ○ | Adapter has no ownership detection (e.g. local-random, you generated it). |
Ownership strategies
Different adapters use different strategies. All read-only, all documented in the evidence string on each check.
| Strategy | Example |
|---|---|
| format-decode | Clerk pk_live_... base64-decodes to a FAPI host; match against your Clerk instances. |
| api-introspection | OpenAI /v1/me returns the org id the key authenticates to. |
| list-match | Neon /projects enumerates your projects; decoded endpoint ids must be in the list. |
| sibling-inheritance | Clerk CLERK_WEBHOOK_SECRET has no owner info; inherits from CLERK_SECRET_KEY in the same project. |
Output
$ rotate-cli who --from-scan --tag non-sensitive Preloading ownership indexes... ✓ clerk · 865ms ✓ upstash · 1.2s ✓ neon-connection · 3.0s ✓ vercel-siblings · 98/126 projects decrypted · 14.3s Checking 451 secret(s)... ✓ clerk-elements-CLERK_SECRET_KEY self [clerk] decoded FAPI host matches known host ✗ upstash-onpe-bot-UPSTASH_REDIS_REST_URL other [upstash] endpoint not in admin's index ? openai-semantik-OPENAI_API_KEY unknown [openai] /v1/me no org info Summary: 77 self (58 unique), 280 other (145 unique), 69 unknown, 22 no-check
The (N unique) tells you how many actual rotations
apply will do, duplicate values across projects get
deduped (see apply).
JSON envelope
{ "command": "preview-ownership", "data": { "checks": [{ "secret_id": "clerk-elements-CLERK_SECRET_KEY", "verdict": "self", "confidence": "high", "strategy": "format-decode", "value_hash": "a1b2c3d4e5f6", "evidence": "decoded FAPI host matches..." }], "summary": { "self": 77, "other": 280, ... }, "unique_counts": { "self": 58, "other": 145 } } }