# tsafe-agent
Background session agent for [tsafe](https://crates.io/crates/tsafe-cli).
Holds an unlocked vault session over a named pipe (Windows) or Unix socket
(macOS / Linux) so subsequent `tsafe` commands skip the password prompt during
the TTL window.
## Install
Included in the default CLI install:
```
cargo install tsafe-cli
```
The agent binary is part of the default build shape alongside the CLI.
## Usage
Start the agent and unlock the vault:
```sh
eval $(tsafe agent unlock --ttl 8h)
```
`eval` is required because the agent prints the socket address and session
token as a shell assignment. The token is never written to shell history this
way.
Once the agent is running, subsequent commands in the same shell session skip
the password prompt:
```sh
tsafe get MY_SECRET
tsafe exec -- my-app
```
To unlock with a specific profile:
```sh
eval $(tsafe agent unlock --profile work --ttl 4h)
```
## TTL
Two TTL values control agent lifetime:
- **Idle TTL** — the agent exits if no request arrives within this window.
- **Absolute TTL** — a hard deadline regardless of activity. Set via
`--ttl`; defaults to 8 hours.
A background watchdog thread enforces the absolute deadline and wakes the
accept loop when it fires so the agent exits promptly.
## Status
```sh
tsafe agent status --json
```
Returns machine-readable agent state including the socket path, profile, and
time remaining.
## Password acquisition
The agent acquires the vault password using this priority chain:
1. **OS keychain** — macOS Keychain or Linux Secret Service, using the same
entry as `tsafe biometric enable`. Single call, no double-prompt.
2. **`TSAFE_VAULT_PASSWORD` env var** — accepted but warned loudly because the
value is visible in `/proc/self/environ` and `docker inspect`. Prefer the
keychain.
3. **Interactive TTY prompt** — via `rpassword`, the original behaviour.
## Security model
- **PID verification** — on each `OpenVault` request, the agent checks that
the `requesting_pid` field in the JSON matches the actual PID of the
connecting process (via `SO_PEERCRED` on Linux, `getpeereid` + `LOCAL_PEERPID`
on macOS, `GetNamedPipeClientProcessId` on Windows). A PID mismatch is
rejected.
- **Socket permissions** — the Unix socket file is created with mode `0600`
(owner-only). On Windows, only one named-pipe instance is created per
session.
- **Zeroize on drop** — the vault password is held in a `Password(String)`
newtype that implements `ZeroizeOnDrop`; the memory is overwritten before
deallocation.
- **Signal handling (Unix)** — `SIGTERM` and `SIGINT` set the stop flag so
the accept loop drains cleanly and the `SocketCleanup` RAII guard unlinks
the socket file. `SIGHUP` is ignored so terminal hangup does not kill the
agent mid-session.
## CellOS broker (Unix only)
On macOS and Linux the agent also binds a second Unix socket for the CellOS
subsystem. CellOS callers authenticate by UID match (`SO_PEERCRED` / `getpeereid`)
and a per-cell token. Supported requests:
- `Resolve` — look up a secret by key and cell ID; registers the cell on first
call and validates the token on subsequent calls.
- `RevokeForCell` — mark a cell ID as revoked; subsequent `Resolve` calls for
that cell are rejected.
Both operations are appended to the profile audit log.
## License
Same as the tsafe workspace — see the repository root.