This project adheres to Hexagonal Architecture (Ports and Adapters) to ensure security, testability, and separation of concerns.
The core logic for managing secrets, independent of the underlying OS.
- Services:
VaultServiceorchestrates secret retrieval, storage, and resolution strategies (env vars vs vault). - Errors: Domain-specific errors (
VaultError,SecretNotFoundError) to abstract low-level failures.
Interfaces for the domain to talk to hosting platforms without knowing the details.
- CommandRunnerPort: Synchronous command execution (used by
KeychainAdapter).
Adapters for external systems.
- Adapters:
KeychainAdapterorchestrates platform-agnostic command flow while relying on injected ports. - Node adapter:
NodeCommandRunnerpluscreateNodeKeychainAdapterwire up the Node runtime (child_process, default platform detection). - Bun adapter:
BunCommandRunner/createBunKeychainAdapterexecute commands viaBun.spawnSyncwhen Bun is detected. - Deno adapter:
DenoCommandRunner/createDenoKeychainAdapterrely onDeno.Commandso the same domain logic can run inside Deno.
src/
├── domain/
│ ├── errors/ # VaultError, etc.
│ └── services/ # VaultService
├── ports/ # CommandRunnerPort
└── infrastructure/
└── adapters/
├── KeychainAdapter.js
├── node/ # NodeCommandRunner, factories
├── bun/ # BunCommandRunner, factories
└── deno/ # DenoCommandRunner, factories
- Zero-Secret Architecture: Secrets are never stored in the codebase or config files.
- Least Privilege: The adapter only requests the specific keys it needs.
- OS-Native: We rely on the OS's encrypted storage (Keychain, etc.) rather than implementing our own encryption.