# pi-credential-vault

Pi extension package that moves managed-provider credential storage out of plaintext `~/.pi/agent/auth.json` and into a selectable backend.

## Status

Implemented now:

- built-in `age`, `keychain`, and `passthrough` backends
- request-time credential injection through provider overrides
- OAuth login and refresh interception for supported providers
- `/vault` commands for setup, import, verify, show, providers, path, and help
- direct `settings.json` configuration plus a minimal `/vault` settings panel
- CI validation and npm publishing through GitHub Actions and semantic-release

Not implemented yet:

- runtime backend plugin registration
- shared storage integration with `pi-multicodex`
- dedicated migration and bootstrap workflows
- full settings UX for all config fields

Use `PLAN.md` for the detailed implementation plan and `ROADMAP.md` for milestone order.

## Install

```bash
pi install npm:@victor-software-house/pi-credential-vault
```

## Quick start

```bash
# Open pi
pi

# For the default age backend, generate a local identity
/vault setup

# Import existing credentials from auth.json into the active backend
/vault import

# Verify the backend and inspect managed providers
/vault verify
/vault show

# Export credentials to another backend or rewrite current backend
/vault export keychain
/vault export age        # same-backend rewrite: re-encrypts with current recipients
```

If you use `pi-multicodex`, exclude `openai-codex` from vault management until shared storage integration is implemented.

## What the extension does

1. Loads `pi-credential-vault` settings from `~/.pi/agent/settings.json`
2. Creates the configured built-in backend
3. Re-registers managed providers through `pi.registerProvider()`
4. Resolves credentials from the active backend before each request
5. Stores OAuth login and refresh results back into the backend
6. Exposes `/vault` commands for setup and inspection

## Architecture

| Area | Files | Responsibility |
|---|---|---|
| Entrypoint | `index.ts`, `src/extension.ts` | Load controller, register commands, expose minimal event-bus API, update session status |
| Types | `src/types.ts` | Credential entry types, backend interface, config types, extension API types |
| Built-in backends | `src/backends/*.ts` | Encrypted file storage, OS keychain storage, passthrough compatibility storage |
| Backend registry | `src/backends/registry.ts` | Create and cache built-in backend instances |
| Configuration | `src/config/*.ts` | Defaults, settings file I/O, normalization, settings panel |
| Provider integration | `src/providers/*.ts` | Provider mirroring, request-time API key resolution, OAuth wrapping |
| Commands | `src/commands/vault-command.ts`, `src/commands/parse-args.ts` | `/vault` command family and argument parsing |
| Services | `src/services/credential-transfer.ts` | Credential transfer between backends |
| Tests | `src/__tests__/*.test.ts` | Backend, registry, command parsing, transfer, and stream helper validation |

## Built-in backends

### `age` (default)

Credentials are encrypted with the `age-encryption` JavaScript library and stored in `~/.pi/agent/vault.age.json` by default.

- safe to commit as ciphertext
- supports additional recipients in config
- reads the local identity from `~/.config/pi-vault/age.txt` or `PI_VAULT_AGE_KEY`

Recipient changes are applied by running `/vault export age`, which re-reads and re-writes every credential with the current recipient list.

### `keychain`

Credentials are stored in the platform keychain through `cross-keychain`.

- macOS: Keychain
- Linux: Secret Service
- Windows: Credential Manager

This backend is suitable for single-machine local storage, not for syncing encrypted files between machines.

### `passthrough`

Credentials are read from and written to Pi's native `auth.json` format.

Use this for backward compatibility or as a fallback when a secure backend is unavailable.

## Configuration

Settings live under the `pi-credential-vault` key in `~/.pi/agent/settings.json`.

```json
{
  "pi-credential-vault": {
    "backend": "age",
    "managedProviders": "all",
    "excludeProviders": ["openai-codex"],
    "age": {
      "vaultPath": "~/.pi/agent/vault.age.json",
      "identityPath": "~/.config/pi-vault/age.txt",
      "recipients": ["age1abc..."]
    },
    "keychain": {
      "service": "pi-credential-vault"
    }
  }
}
```

| Setting | Type | Notes |
|---|---|---|
| `backend` | `age \| keychain \| passthrough` | Active built-in backend |
| `managedProviders` | `"all" \| string[]` | Which provider IDs are managed by the extension |
| `excludeProviders` | `string[]` | Providers intentionally left to other extensions or native Pi behavior |
| `age.vaultPath` | `string` | Optional encrypted vault file path |
| `age.identityPath` | `string` | Optional age identity path |
| `age.recipients` | `string[]` | Additional age recipients |
| `keychain.service` | `string` | Service name used in the OS keychain |

## Commands

| Command | Current behavior |
|---|---|
| `/vault` | Open the settings panel |
| `/vault show` | Show active backend status, credential count, and managed providers |
| `/vault verify` | Check backend health and stored credential count |
| `/vault providers` | Show managed and excluded provider IDs with scope |
| `/vault setup` | Generate an age identity for the default backend |
| `/vault import` | Import credentials from `auth.json` into the active backend |
| `/vault export [target]` | Export credentials to a target backend. Same-backend export rewrites all entries (forces re-encryption for age). |
| `/vault path` | Show backend-specific file or service locations |
| `/vault help` | Show command summary |

## Operator notes

### `pi-multicodex` coexistence

Today, `pi-credential-vault` and `pi-multicodex` should not both manage `openai-codex`.

```json
{
  "pi-credential-vault": {
    "excludeProviders": ["openai-codex"]
  }
}
```

Shared storage integration remains planned work.

### Fallback behavior

If the configured backend is unavailable at startup, the extension currently leaves providers on native Pi behavior and reports the problem through session status and `/vault verify`.

### Status indicator

The repository contains a placeholder status-line module, but current status reporting is performed directly from `src/extension.ts` during session events.

## Development

Install dependencies and run the current validation commands:

```bash
pnpm install
pnpm typecheck
pnpm test
npm pack --dry-run
```

Notes:

- There is currently no repository source-lint script.
- CI runs commitlint, typecheck, test, and `npm pack --dry-run`.
- Releases are produced by semantic-release from `.github/workflows/publish.yml`.

## Release and documentation rules

- `README.md` describes implemented behavior only.
- `ROADMAP.md` tracks milestone order, not pre-assigned semantic versions.
- `PLAN.md` contains detailed implementation sequencing and design constraints.
- `AGENTS.md` contains repository-specific contributor and automation rules.
- `package.json` is part of the operational contract for scripts, package metadata, publish shape, and extension entrypoints.
- When command surface, config shape, release flow, packaging, or architecture changes, update all relevant files together, including `package.json` when manifest-facing behavior changes.

## Known limitations

- The backend registry only supports built-in backends.
- The settings panel currently edits only a subset of config.
- There is no multi-step migration workflow yet (`/vault export` copies but does not clean up source data).

## Related documents

- `PLAN.md` — detailed implementation plan and phased delivery
- `ROADMAP.md` — ordered milestone view
- `AGENTS.md` — contributor and automation guidance
