Skip to content

Commit eb4d5c2

Browse files
committed
docs: add v0.2 feature specs and web package-lock
Add specification documents for v0.2 features: JSON output, env command, dotenv import, export, non-interactive mode, structured errors, and agent discovery.
1 parent 3e9d2ff commit eb4d5c2

File tree

10 files changed

+3230
-0
lines changed

10 files changed

+3230
-0
lines changed

docs/specs/v0.2/01-json-output.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# 01 — JSON Output (`--json`)
2+
3+
## Summary
4+
5+
Add a `--json` flag to commands that produce output, so agents can parse responses reliably without scraping text.
6+
7+
## Motivation
8+
9+
Today, `authy get` outputs a raw string. `authy list` outputs one name per line. `authy session list` outputs a formatted table. None of these are machine-parseable without brittle string splitting. AI agents that call `authy` via bash need structured output to make decisions based on the result.
10+
11+
## Current Behavior
12+
13+
```
14+
$ authy get db-url
15+
postgresql://user:pass@host/db
16+
17+
$ authy list
18+
api-key
19+
db-url
20+
github-token
21+
22+
$ authy session list
23+
ID SCOPE STATUS EXPIRES
24+
abc123 deploy active 2h remaining
25+
def456 dev-agent expired —
26+
27+
$ authy policy show deploy
28+
Name: deploy
29+
Allow: db-*, github-token
30+
Deny: prod-*
31+
Description: Deploy agent policy
32+
```
33+
34+
## Proposed Behavior
35+
36+
### Global `--json` flag
37+
38+
Add `--json` as a global flag on the root `Cli` struct (clap). When present, all output-producing commands emit JSON to stdout.
39+
40+
### Per-command output schemas
41+
42+
**`authy get <name> --json`**
43+
44+
```json
45+
{
46+
"name": "db-url",
47+
"value": "postgresql://user:pass@host/db",
48+
"version": 3,
49+
"created": "2026-02-10T08:30:00Z",
50+
"modified": "2026-02-15T14:22:00Z"
51+
}
52+
```
53+
54+
**`authy list --json`**
55+
56+
```json
57+
{
58+
"secrets": [
59+
{
60+
"name": "api-key",
61+
"version": 1,
62+
"created": "2026-02-10T08:30:00Z",
63+
"modified": "2026-02-10T08:30:00Z"
64+
},
65+
{
66+
"name": "db-url",
67+
"version": 3,
68+
"created": "2026-02-10T08:30:00Z",
69+
"modified": "2026-02-15T14:22:00Z"
70+
}
71+
]
72+
}
73+
```
74+
75+
Note: `list --json` does NOT include secret values. Use `get` for values.
76+
77+
**`authy policy show <name> --json`**
78+
79+
```json
80+
{
81+
"name": "deploy",
82+
"allow": ["db-*", "github-token"],
83+
"deny": ["prod-*"],
84+
"description": "Deploy agent policy"
85+
}
86+
```
87+
88+
**`authy policy list --json`**
89+
90+
```json
91+
{
92+
"policies": [
93+
{
94+
"name": "deploy",
95+
"allow_count": 2,
96+
"deny_count": 1,
97+
"description": "Deploy agent policy"
98+
}
99+
]
100+
}
101+
```
102+
103+
**`authy policy test --scope <scope> <name> --json`**
104+
105+
```json
106+
{
107+
"secret": "db-url",
108+
"scope": "deploy",
109+
"allowed": true
110+
}
111+
```
112+
113+
**`authy session list --json`**
114+
115+
```json
116+
{
117+
"sessions": [
118+
{
119+
"id": "abc123",
120+
"scope": "deploy",
121+
"label": "ci-deploy",
122+
"status": "active",
123+
"created": "2026-02-15T10:00:00Z",
124+
"expires": "2026-02-15T18:00:00Z"
125+
}
126+
]
127+
}
128+
```
129+
130+
**`authy session create --json`**
131+
132+
```json
133+
{
134+
"token": "authy_v1.dGhpcyBpcyBhIDMyIGJ5dGUg...",
135+
"session_id": "abc123",
136+
"scope": "deploy",
137+
"expires": "2026-02-15T18:00:00Z"
138+
}
139+
```
140+
141+
**`authy audit show --json`**
142+
143+
```json
144+
{
145+
"entries": [
146+
{
147+
"timestamp": "2026-02-15T14:22:00Z",
148+
"operation": "secret_read",
149+
"secret": "db-url",
150+
"actor": "token:abc123",
151+
"outcome": "granted",
152+
"detail": ""
153+
}
154+
]
155+
}
156+
```
157+
158+
### Commands NOT affected
159+
160+
- `authy get` (without `--json`): unchanged, raw value to stdout
161+
- `authy run`: passthrough to child process, `--json` has no effect
162+
- `authy admin`: TUI, `--json` has no effect
163+
- `authy config show`: already TOML, `--json` could optionally emit JSON
164+
- `authy audit export`: already JSON, `--json` is redundant (no-op)
165+
166+
### Error output with `--json`
167+
168+
When `--json` is set and an error occurs, stderr emits a JSON error object instead of a plain message. See [06-structured-errors.md](06-structured-errors.md).
169+
170+
## Interface
171+
172+
```
173+
authy [--json] <command> [args...]
174+
```
175+
176+
The `--json` flag is positional on the root parser, before the subcommand.
177+
178+
## Edge Cases
179+
180+
- `--json` + pipe to another command: works naturally (stdout is JSON)
181+
- `--json` + `authy get`: includes metadata (name, version, timestamps), not just raw value
182+
- `--json` + `authy run`: ignored silently (child process owns stdout)
183+
- `--json` + `authy admin`: ignored silently (TUI owns terminal)
184+
- Empty list results: return `{"secrets": []}`, not an error
185+
186+
## Acceptance Criteria
187+
188+
- [ ] `--json` flag available on root CLI
189+
- [ ] `get`, `list`, `policy show`, `policy list`, `policy test`, `session list`, `session create`, `audit show` all produce valid JSON when `--json` is set
190+
- [ ] JSON output goes to stdout; no diagnostic messages mixed in
191+
- [ ] Without `--json`, all commands behave identically to today
192+
- [ ] All JSON output is valid (parseable by `jq`)

docs/specs/v0.2/02-env-command.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# 02 — Env Command (`authy env`)
2+
3+
## Summary
4+
5+
New `authy env` command that outputs scoped secrets as shell-sourceable environment variable declarations. The bridge between Authy's encrypted vault and the `export FOO=bar` world that every tool and agent already understands.
6+
7+
## Motivation
8+
9+
Today, `authy run --scope X -- cmd` spawns a child process with env vars injected. This works for launching a single process, but doesn't help when:
10+
11+
1. A shell session needs multiple tools to see the same secrets
12+
2. A `SessionStart` hook needs to write env vars to `CLAUDE_ENV_FILE`
13+
3. A CI pipeline step needs to source secrets into the current shell
14+
4. A container entrypoint needs to set up the environment before exec
15+
16+
`authy env` produces the text output that feeds these use cases. It's the composable building block — the output can be `eval`'d, appended to files, piped, or redirected.
17+
18+
## Current Behavior
19+
20+
No `authy env` command exists. The closest is `authy run`, which spawns a subprocess.
21+
22+
## Proposed Behavior
23+
24+
### Basic usage
25+
26+
```bash
27+
$ authy env --scope deploy
28+
export DB_URL='postgresql://user:pass@host/db'
29+
export GITHUB_TOKEN='ghp_xxxxxxxxxxxx'
30+
```
31+
32+
Output is `export KEY='VALUE'` format, one per line. Directly sourceable by bash/zsh.
33+
34+
### Source it
35+
36+
```bash
37+
eval "$(authy env --scope deploy)"
38+
# DB_URL and GITHUB_TOKEN are now in the current shell
39+
```
40+
41+
### Write to a file
42+
43+
```bash
44+
authy env --scope deploy >> "$CLAUDE_ENV_FILE"
45+
```
46+
47+
### Flags
48+
49+
```
50+
authy env --scope <SCOPE> [--uppercase] [--replace-dash <CHAR>] [--prefix <PREFIX>] [--format <FORMAT>] [--no-export]
51+
```
52+
53+
| Flag | Default | Description |
54+
|------|---------|-------------|
55+
| `--scope <SCOPE>` | required | Policy scope to filter secrets |
56+
| `--uppercase` | off | Convert secret names to UPPERCASE |
57+
| `--replace-dash <CHAR>` | none | Replace `-` in names with given character |
58+
| `--prefix <PREFIX>` | none | Prepend prefix to each variable name |
59+
| `--format <FORMAT>` | `shell` | Output format (see below) |
60+
| `--no-export` | off | Omit `export` keyword (just `KEY='VALUE'`) |
61+
62+
These flags mirror `authy run` for consistency.
63+
64+
### Output formats
65+
66+
**`--format shell`** (default)
67+
68+
```bash
69+
export DB_URL='postgresql://user:pass@host/db'
70+
export GITHUB_TOKEN='ghp_xxxxxxxxxxxx'
71+
```
72+
73+
**`--format dotenv`**
74+
75+
```
76+
DB_URL=postgresql://user:pass@host/db
77+
GITHUB_TOKEN=ghp_xxxxxxxxxxxx
78+
```
79+
80+
Standard `.env` format (no `export`, no quoting unless value contains special chars). Values with spaces, `#`, or newlines are double-quoted.
81+
82+
**`--format json`**
83+
84+
```json
85+
{
86+
"DB_URL": "postgresql://user:pass@host/db",
87+
"GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"
88+
}
89+
```
90+
91+
Flat key-value JSON object.
92+
93+
### Name transformation
94+
95+
Transformation order: (1) replace-dash, (2) prefix, (3) uppercase.
96+
97+
```bash
98+
$ authy env --scope deploy --uppercase --replace-dash _ --prefix AUTHY_
99+
export AUTHY_DB_URL='postgresql://user:pass@host/db'
100+
export AUTHY_GITHUB_TOKEN='ghp_xxxxxxxxxxxx'
101+
```
102+
103+
This matches the existing `authy run` transformation behavior.
104+
105+
### Authentication
106+
107+
Supports all auth methods: passphrase, keyfile, session token. When using a session token, the token's scope is used and `--scope` is optional (defaults to token scope).
108+
109+
## Edge Cases
110+
111+
- Empty scope (no secrets match policy): output nothing, exit 0
112+
- Secret value contains single quotes: escape as `'\''` in shell format
113+
- Secret value contains newlines: use `$'...\n...'` quoting in shell format; `"..."` with `\n` in dotenv
114+
- `--scope` required unless using session token (which has implicit scope)
115+
- `--format json` ignores `--no-export` (not applicable)
116+
117+
## Relationship to `authy run`
118+
119+
`authy env` and `authy run` share the same policy evaluation and name transformation logic. Internally, `authy run` could be refactored to use the same secret-resolution code as `authy env`, then pass the result to `Command::envs()`.
120+
121+
## Use Cases
122+
123+
**Claude Code SessionStart hook:**
124+
```bash
125+
#!/bin/bash
126+
if [ -n "$CLAUDE_ENV_FILE" ]; then
127+
authy env --scope claude-code --uppercase --replace-dash _ >> "$CLAUDE_ENV_FILE"
128+
fi
129+
```
130+
131+
**Docker container entrypoint:**
132+
```bash
133+
#!/bin/bash
134+
eval "$(authy env --scope $AGENT_SCOPE --uppercase --replace-dash _)"
135+
exec "$@"
136+
```
137+
138+
**CI pipeline step:**
139+
```bash
140+
eval "$(authy env --scope ci-deploy --uppercase --replace-dash _)"
141+
./deploy.sh
142+
```
143+
144+
**Pipe to another tool:**
145+
```bash
146+
authy env --scope dev --format json | jq '.DB_URL'
147+
```
148+
149+
## Acceptance Criteria
150+
151+
- [ ] `authy env --scope <scope>` outputs shell-sourceable `export` statements
152+
- [ ] `--format shell`, `--format dotenv`, `--format json` all work
153+
- [ ] `--uppercase`, `--replace-dash`, `--prefix` transform names correctly
154+
- [ ] `--no-export` omits `export` keyword in shell format
155+
- [ ] Values with special characters are properly escaped per format
156+
- [ ] Empty result (no matching secrets) outputs nothing, exits 0
157+
- [ ] Works with all auth methods (passphrase, keyfile, token)
158+
- [ ] Audit log records the access (operation: `env_export`, lists scope)

0 commit comments

Comments
 (0)