@ewimsatt/agent-vault 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +67 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +106 -0
- package/dist/manifest.js.map +1 -0
- package/dist/metadata.d.ts +33 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +50 -0
- package/dist/metadata.js.map +1 -0
- package/dist/vault.d.ts +89 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +215 -0
- package/dist/vault.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# agent-vault — Node.js SDK
|
|
2
|
+
|
|
3
|
+
Zero-trust credential manager for AI agents. This is the read-only Node.js/TypeScript SDK for retrieving secrets from an agent-vault repository.
|
|
4
|
+
|
|
5
|
+
Secrets are encrypted locally using [age encryption](https://age-encryption.org/) and synced via Git. No server, no SaaS -- the Git repo is an untrusted encrypted blob store. All crypto happens locally.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install agent-vault
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires Node.js 20 or later.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { Vault } from "agent-vault";
|
|
19
|
+
|
|
20
|
+
const vault = new Vault({
|
|
21
|
+
repoPath: "/path/to/repo",
|
|
22
|
+
keyPath: "~/.agent-vault/agents/my-agent.key",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Decrypt a secret (pulls latest from Git first)
|
|
26
|
+
const apiKey = await vault.get("stripe/api-key");
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
### `new Vault(options)`
|
|
32
|
+
|
|
33
|
+
Create a read-only vault instance.
|
|
34
|
+
|
|
35
|
+
| Option | Type | Default | Description |
|
|
36
|
+
|------------|-----------|---------|--------------------------------------------------|
|
|
37
|
+
| `repoPath` | `string` | - | Path to the Git repository containing the vault. |
|
|
38
|
+
| `keyPath` | `string?` | - | Path to the age private key file. |
|
|
39
|
+
| `keyStr` | `string?` | - | Raw age private key string. Overrides `keyPath`. |
|
|
40
|
+
| `autoPull` | `boolean` | `true` | Whether to `git pull` before each `get()` call. |
|
|
41
|
+
|
|
42
|
+
Key resolution order:
|
|
43
|
+
1. `keyStr` option
|
|
44
|
+
2. `keyPath` option
|
|
45
|
+
3. `AGENT_VAULT_KEY` environment variable
|
|
46
|
+
4. `~/.agent-vault/owner.key`
|
|
47
|
+
|
|
48
|
+
### `vault.get(secretPath): Promise<string>`
|
|
49
|
+
|
|
50
|
+
Decrypt and return a secret value. The secret path follows the format `group/name` (e.g., `stripe/api-key`).
|
|
51
|
+
|
|
52
|
+
Throws `SecretNotFoundError` if the secret does not exist. Throws `NotAuthorizedError` if the key cannot decrypt it.
|
|
53
|
+
|
|
54
|
+
### `vault.listSecrets(group?): SecretMetadata[]`
|
|
55
|
+
|
|
56
|
+
List secret metadata without decrypting. Optionally filter by group name.
|
|
57
|
+
|
|
58
|
+
### `vault.pull(): void`
|
|
59
|
+
|
|
60
|
+
Manually trigger a `git pull`. Failures are logged to stderr but do not throw.
|
|
61
|
+
|
|
62
|
+
### `vault.listAgents(): Array<{ name: string; groups: string[] }>`
|
|
63
|
+
|
|
64
|
+
List all agents and their group memberships from the manifest.
|
|
65
|
+
|
|
66
|
+
### `vault.reload(): void`
|
|
67
|
+
|
|
68
|
+
Reload the manifest from disk (useful after a pull).
|
|
69
|
+
|
|
70
|
+
## Error Types
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import {
|
|
74
|
+
VaultError, // Base error
|
|
75
|
+
VaultNotFoundError, // No vault or key found
|
|
76
|
+
SecretNotFoundError, // Secret path does not exist
|
|
77
|
+
NotAuthorizedError, // Key cannot decrypt the secret
|
|
78
|
+
ManifestError, // Manifest parsing failure
|
|
79
|
+
} from "agent-vault";
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Environment Variables
|
|
83
|
+
|
|
84
|
+
- `AGENT_VAULT_KEY` -- Raw age secret key string (used if no `keyPath`/`keyStr` provided)
|
|
85
|
+
|
|
86
|
+
## How It Works
|
|
87
|
+
|
|
88
|
+
1. The vault reads encrypted `.enc` files from `.agent-vault/secrets/` in the repo.
|
|
89
|
+
2. It decrypts them in memory using the [age-encryption](https://www.npmjs.com/package/age-encryption) package.
|
|
90
|
+
3. Decrypted values are never written to disk -- they exist only in memory.
|
|
91
|
+
4. Metadata (`.meta` YAML files) can be browsed without decryption.
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error types for agent-vault.
|
|
3
|
+
*/
|
|
4
|
+
/** Base error for all vault operations. */
|
|
5
|
+
export declare class VaultError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/** No .agent-vault directory found at the given path. */
|
|
9
|
+
export declare class VaultNotFoundError extends VaultError {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
/** The requested secret does not exist in the vault. */
|
|
13
|
+
export declare class SecretNotFoundError extends VaultError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
/** The provided key cannot decrypt the requested secret. */
|
|
17
|
+
export declare class NotAuthorizedError extends VaultError {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
20
|
+
/** Error parsing or querying the manifest. */
|
|
21
|
+
export declare class ManifestError extends VaultError {
|
|
22
|
+
constructor(message: string);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2CAA2C;AAC3C,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAK5B;AAED,yDAAyD;AACzD,qBAAa,kBAAmB,SAAQ,UAAU;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,wDAAwD;AACxD,qBAAa,mBAAoB,SAAQ,UAAU;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED,4DAA4D;AAC5D,qBAAa,kBAAmB,SAAQ,UAAU;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,8CAA8C;AAC9C,qBAAa,aAAc,SAAQ,UAAU;gBAC/B,OAAO,EAAE,MAAM;CAI5B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error types for agent-vault.
|
|
3
|
+
*/
|
|
4
|
+
/** Base error for all vault operations. */
|
|
5
|
+
export class VaultError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "VaultError";
|
|
9
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** No .agent-vault directory found at the given path. */
|
|
13
|
+
export class VaultNotFoundError extends VaultError {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "VaultNotFoundError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** The requested secret does not exist in the vault. */
|
|
20
|
+
export class SecretNotFoundError extends VaultError {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = "SecretNotFoundError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** The provided key cannot decrypt the requested secret. */
|
|
27
|
+
export class NotAuthorizedError extends VaultError {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "NotAuthorizedError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Error parsing or querying the manifest. */
|
|
34
|
+
export class ManifestError extends VaultError {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "ManifestError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2CAA2C;AAC3C,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAED,yDAAyD;AACzD,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,wDAAwD;AACxD,MAAM,OAAO,mBAAoB,SAAQ,UAAU;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,4DAA4D;AAC5D,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,8CAA8C;AAC9C,MAAM,OAAO,aAAc,SAAQ,UAAU;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-vault: Zero-trust credential manager for AI agents — Node.js SDK.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
export { Vault, type VaultOptions } from "./vault.js";
|
|
7
|
+
export { VaultError, VaultNotFoundError, SecretNotFoundError, NotAuthorizedError, ManifestError, } from "./errors.js";
|
|
8
|
+
export { type SecretMetadata, parseMetadataFile, parseMetadata } from "./metadata.js";
|
|
9
|
+
export { Manifest, type ManifestAgent, type ManifestGroup } from "./manifest.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-vault: Zero-trust credential manager for AI agents — Node.js SDK.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
export { Vault } from "./vault.js";
|
|
7
|
+
export { VaultError, VaultNotFoundError, SecretNotFoundError, NotAuthorizedError, ManifestError, } from "./errors.js";
|
|
8
|
+
export { parseMetadataFile, parseMetadata } from "./metadata.js";
|
|
9
|
+
export { Manifest } from "./manifest.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAqB,MAAM,YAAY,CAAC;AACtD,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAuB,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,QAAQ,EAA0C,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest parsing for vault access control.
|
|
3
|
+
*
|
|
4
|
+
* The manifest.yaml file defines which agents can access which groups of secrets.
|
|
5
|
+
* It contains no secret material — only plaintext policy.
|
|
6
|
+
*/
|
|
7
|
+
/** A single agent entry in the manifest. */
|
|
8
|
+
export interface ManifestAgent {
|
|
9
|
+
name: string;
|
|
10
|
+
groups: string[];
|
|
11
|
+
}
|
|
12
|
+
/** A secret group entry in the manifest. */
|
|
13
|
+
export interface ManifestGroup {
|
|
14
|
+
name: string;
|
|
15
|
+
secrets: string[];
|
|
16
|
+
}
|
|
17
|
+
/** Parsed manifest data. */
|
|
18
|
+
interface ManifestData {
|
|
19
|
+
version?: number;
|
|
20
|
+
owners?: Array<{
|
|
21
|
+
name: string;
|
|
22
|
+
public_key?: string;
|
|
23
|
+
}>;
|
|
24
|
+
agents?: Array<{
|
|
25
|
+
name: string;
|
|
26
|
+
groups?: string[];
|
|
27
|
+
}>;
|
|
28
|
+
groups?: Array<{
|
|
29
|
+
name: string;
|
|
30
|
+
secrets?: string[];
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parsed manifest.yaml — access control policy.
|
|
35
|
+
*/
|
|
36
|
+
export declare class Manifest {
|
|
37
|
+
private readonly _data;
|
|
38
|
+
private readonly _agents;
|
|
39
|
+
private readonly _groups;
|
|
40
|
+
constructor(data: ManifestData);
|
|
41
|
+
/**
|
|
42
|
+
* Load a manifest from a YAML file.
|
|
43
|
+
*
|
|
44
|
+
* @param filePath - Absolute path to manifest.yaml.
|
|
45
|
+
* @returns Parsed Manifest.
|
|
46
|
+
* @throws ManifestError if the file is missing or invalid.
|
|
47
|
+
*/
|
|
48
|
+
static load(filePath: string): Manifest;
|
|
49
|
+
/** Return the list of groups an agent belongs to. */
|
|
50
|
+
agentGroups(agentName: string): string[];
|
|
51
|
+
/** Return the list of secret paths in a group. */
|
|
52
|
+
groupSecrets(groupName: string): string[];
|
|
53
|
+
/** Return agent names authorized for a given secret. */
|
|
54
|
+
agentsForSecret(secretPath: string): string[];
|
|
55
|
+
/** Return all agents with their group memberships. */
|
|
56
|
+
listAgents(): ManifestAgent[];
|
|
57
|
+
/** Return all group names. */
|
|
58
|
+
listGroups(): string[];
|
|
59
|
+
/**
|
|
60
|
+
* Return all secret paths, optionally filtered by group.
|
|
61
|
+
*
|
|
62
|
+
* @param group - Optional group name to filter by.
|
|
63
|
+
*/
|
|
64
|
+
listSecrets(group?: string): string[];
|
|
65
|
+
}
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,4BAA4B;AAC5B,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACpD,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACtD;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;gBAEzC,IAAI,EAAE,YAAY;IAoB9B;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAsBvC,qDAAqD;IACrD,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAKxC,kDAAkD;IAClD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAKzC,wDAAwD;IACxD,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAc7C,sDAAsD;IACtD,UAAU,IAAI,aAAa,EAAE;IAI7B,8BAA8B;IAC9B,UAAU,IAAI,MAAM,EAAE;IAItB;;;;OAIG;IACH,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;CAUtC"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest parsing for vault access control.
|
|
3
|
+
*
|
|
4
|
+
* The manifest.yaml file defines which agents can access which groups of secrets.
|
|
5
|
+
* It contains no secret material — only plaintext policy.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import yaml from "js-yaml";
|
|
9
|
+
import { ManifestError } from "./errors.js";
|
|
10
|
+
/**
|
|
11
|
+
* Parsed manifest.yaml — access control policy.
|
|
12
|
+
*/
|
|
13
|
+
export class Manifest {
|
|
14
|
+
_data;
|
|
15
|
+
_agents;
|
|
16
|
+
_groups;
|
|
17
|
+
constructor(data) {
|
|
18
|
+
this._data = data;
|
|
19
|
+
this._agents = new Map();
|
|
20
|
+
for (const a of data.agents ?? []) {
|
|
21
|
+
this._agents.set(a.name, {
|
|
22
|
+
name: a.name,
|
|
23
|
+
groups: [...(a.groups ?? [])],
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
this._groups = new Map();
|
|
27
|
+
for (const g of data.groups ?? []) {
|
|
28
|
+
this._groups.set(g.name, {
|
|
29
|
+
name: g.name,
|
|
30
|
+
secrets: [...(g.secrets ?? [])],
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Load a manifest from a YAML file.
|
|
36
|
+
*
|
|
37
|
+
* @param filePath - Absolute path to manifest.yaml.
|
|
38
|
+
* @returns Parsed Manifest.
|
|
39
|
+
* @throws ManifestError if the file is missing or invalid.
|
|
40
|
+
*/
|
|
41
|
+
static load(filePath) {
|
|
42
|
+
let content;
|
|
43
|
+
try {
|
|
44
|
+
content = readFileSync(filePath, "utf-8");
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
throw new ManifestError(`Manifest not found: ${filePath}`);
|
|
48
|
+
}
|
|
49
|
+
let data;
|
|
50
|
+
try {
|
|
51
|
+
data = yaml.load(content) ?? {};
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
throw new ManifestError(`Invalid manifest YAML: ${err instanceof Error ? err.message : String(err)}`);
|
|
55
|
+
}
|
|
56
|
+
return new Manifest(data);
|
|
57
|
+
}
|
|
58
|
+
/** Return the list of groups an agent belongs to. */
|
|
59
|
+
agentGroups(agentName) {
|
|
60
|
+
const agent = this._agents.get(agentName);
|
|
61
|
+
return agent ? [...agent.groups] : [];
|
|
62
|
+
}
|
|
63
|
+
/** Return the list of secret paths in a group. */
|
|
64
|
+
groupSecrets(groupName) {
|
|
65
|
+
const group = this._groups.get(groupName);
|
|
66
|
+
return group ? [...group.secrets] : [];
|
|
67
|
+
}
|
|
68
|
+
/** Return agent names authorized for a given secret. */
|
|
69
|
+
agentsForSecret(secretPath) {
|
|
70
|
+
const agents = [];
|
|
71
|
+
for (const [agentName, agent] of this._agents) {
|
|
72
|
+
for (const groupName of agent.groups) {
|
|
73
|
+
const group = this._groups.get(groupName);
|
|
74
|
+
if (group && group.secrets.includes(secretPath)) {
|
|
75
|
+
agents.push(agentName);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return agents;
|
|
81
|
+
}
|
|
82
|
+
/** Return all agents with their group memberships. */
|
|
83
|
+
listAgents() {
|
|
84
|
+
return Array.from(this._agents.values());
|
|
85
|
+
}
|
|
86
|
+
/** Return all group names. */
|
|
87
|
+
listGroups() {
|
|
88
|
+
return Array.from(this._groups.keys());
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Return all secret paths, optionally filtered by group.
|
|
92
|
+
*
|
|
93
|
+
* @param group - Optional group name to filter by.
|
|
94
|
+
*/
|
|
95
|
+
listSecrets(group) {
|
|
96
|
+
if (group !== undefined) {
|
|
97
|
+
return this.groupSecrets(group);
|
|
98
|
+
}
|
|
99
|
+
const secrets = [];
|
|
100
|
+
for (const g of this._groups.values()) {
|
|
101
|
+
secrets.push(...g.secrets);
|
|
102
|
+
}
|
|
103
|
+
return secrets;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret metadata parsing.
|
|
3
|
+
*/
|
|
4
|
+
/** Plaintext metadata for a single secret. */
|
|
5
|
+
export interface SecretMetadata {
|
|
6
|
+
/** Secret name identifier. */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Group this secret belongs to. */
|
|
9
|
+
group: string;
|
|
10
|
+
/** When the secret was first created. */
|
|
11
|
+
createdAt: Date;
|
|
12
|
+
/** When the secret was last rotated. */
|
|
13
|
+
rotatedAt: Date;
|
|
14
|
+
/** Optional expiration date. */
|
|
15
|
+
expiresAt?: Date;
|
|
16
|
+
/** List of agent names authorized to access this secret. */
|
|
17
|
+
authorizedAgents: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse a .meta YAML file into a SecretMetadata object.
|
|
21
|
+
*
|
|
22
|
+
* @param filePath - Absolute path to the .meta file.
|
|
23
|
+
* @returns Parsed SecretMetadata.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseMetadataFile(filePath: string): SecretMetadata;
|
|
26
|
+
/**
|
|
27
|
+
* Parse metadata from a YAML string.
|
|
28
|
+
*
|
|
29
|
+
* @param content - YAML string content.
|
|
30
|
+
* @returns Parsed SecretMetadata.
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseMetadata(content: string): SecretMetadata;
|
|
33
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,SAAS,EAAE,IAAI,CAAC;IAChB,wCAAwC;IACxC,SAAS,EAAE,IAAI,CAAC;IAChB,gCAAgC;IAChC,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAkBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAGlE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAa7D"}
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret metadata parsing.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import yaml from "js-yaml";
|
|
6
|
+
/**
|
|
7
|
+
* Parse a datetime value from YAML, which may be a Date object or ISO string.
|
|
8
|
+
*/
|
|
9
|
+
function parseDate(val) {
|
|
10
|
+
if (val instanceof Date) {
|
|
11
|
+
return val;
|
|
12
|
+
}
|
|
13
|
+
if (typeof val === "string") {
|
|
14
|
+
const d = new Date(val);
|
|
15
|
+
if (!isNaN(d.getTime())) {
|
|
16
|
+
return d;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return new Date(0);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a .meta YAML file into a SecretMetadata object.
|
|
23
|
+
*
|
|
24
|
+
* @param filePath - Absolute path to the .meta file.
|
|
25
|
+
* @returns Parsed SecretMetadata.
|
|
26
|
+
*/
|
|
27
|
+
export function parseMetadataFile(filePath) {
|
|
28
|
+
const content = readFileSync(filePath, "utf-8");
|
|
29
|
+
return parseMetadata(content);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse metadata from a YAML string.
|
|
33
|
+
*
|
|
34
|
+
* @param content - YAML string content.
|
|
35
|
+
* @returns Parsed SecretMetadata.
|
|
36
|
+
*/
|
|
37
|
+
export function parseMetadata(content) {
|
|
38
|
+
const data = yaml.load(content) ?? {};
|
|
39
|
+
return {
|
|
40
|
+
name: typeof data.name === "string" ? data.name : "",
|
|
41
|
+
group: typeof data.group === "string" ? data.group : "",
|
|
42
|
+
createdAt: parseDate(data.created),
|
|
43
|
+
rotatedAt: parseDate(data.rotated),
|
|
44
|
+
expiresAt: data.expires ? parseDate(data.expires) : undefined,
|
|
45
|
+
authorizedAgents: Array.isArray(data.authorized_agents)
|
|
46
|
+
? data.authorized_agents
|
|
47
|
+
: [],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,SAAS,CAAC;AAkB3B;;GAEG;AACH,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,GAAG,YAAY,IAAI,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,IAAI,GAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAA6B,IAAI,EAAE,CAAC;IAEnE,OAAO;QACL,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QACpD,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QACvD,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;QAClC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;QAClC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7D,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC;YACrD,CAAC,CAAE,IAAI,CAAC,iBAA8B;YACtC,CAAC,CAAC,EAAE;KACP,CAAC;AACJ,CAAC"}
|
package/dist/vault.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main Vault class — read-only agent access to secrets.
|
|
3
|
+
*
|
|
4
|
+
* The Vault handles key loading, Git synchronization, and age decryption.
|
|
5
|
+
* Decrypted material is never written to disk — it stays in memory only.
|
|
6
|
+
*/
|
|
7
|
+
import { Manifest } from "./manifest.js";
|
|
8
|
+
import { type SecretMetadata } from "./metadata.js";
|
|
9
|
+
/** Options for constructing a Vault instance. */
|
|
10
|
+
export interface VaultOptions {
|
|
11
|
+
/** Path to the Git repository containing the vault. */
|
|
12
|
+
repoPath: string;
|
|
13
|
+
/**
|
|
14
|
+
* Path to the age private key file.
|
|
15
|
+
* Falls back to AGENT_VAULT_KEY env var, then ~/.agent-vault/owner.key.
|
|
16
|
+
*/
|
|
17
|
+
keyPath?: string;
|
|
18
|
+
/** Raw age private key string. Overrides keyPath. */
|
|
19
|
+
keyStr?: string;
|
|
20
|
+
/** Whether to git pull before each get() call. Defaults to true. */
|
|
21
|
+
autoPull?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Read-only vault for agents to retrieve secrets.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const vault = new Vault({
|
|
29
|
+
* repoPath: "/path/to/repo",
|
|
30
|
+
* keyPath: "~/.agent-vault/agents/my-agent.key",
|
|
31
|
+
* });
|
|
32
|
+
* const apiKey = await vault.get("stripe/api-key");
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class Vault {
|
|
36
|
+
private readonly _repoPath;
|
|
37
|
+
private readonly _vaultDir;
|
|
38
|
+
private readonly _identity;
|
|
39
|
+
private readonly _autoPull;
|
|
40
|
+
private _manifest;
|
|
41
|
+
constructor(options: VaultOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Resolve and load the age identity (private key).
|
|
44
|
+
*
|
|
45
|
+
* Priority:
|
|
46
|
+
* 1. keyStr option (raw string)
|
|
47
|
+
* 2. keyPath option (file path)
|
|
48
|
+
* 3. AGENT_VAULT_KEY env var (raw string)
|
|
49
|
+
* 4. ~/.agent-vault/owner.key (default file)
|
|
50
|
+
*/
|
|
51
|
+
private _loadIdentity;
|
|
52
|
+
/**
|
|
53
|
+
* Pull latest changes from the Git remote (best-effort).
|
|
54
|
+
*
|
|
55
|
+
* Failures are logged to stderr but do not throw. The vault continues
|
|
56
|
+
* with whatever local state is available.
|
|
57
|
+
*/
|
|
58
|
+
pull(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Retrieve and decrypt a secret.
|
|
61
|
+
*
|
|
62
|
+
* @param secretPath - The secret path (e.g. "stripe/api-key").
|
|
63
|
+
* @returns The decrypted plaintext value.
|
|
64
|
+
* @throws SecretNotFoundError if the secret does not exist.
|
|
65
|
+
* @throws NotAuthorizedError if the key cannot decrypt the secret.
|
|
66
|
+
*/
|
|
67
|
+
get(secretPath: string): Promise<string>;
|
|
68
|
+
/**
|
|
69
|
+
* List secret metadata without decrypting.
|
|
70
|
+
*
|
|
71
|
+
* @param group - Optional group name to filter by.
|
|
72
|
+
* @returns Array of SecretMetadata objects.
|
|
73
|
+
*/
|
|
74
|
+
listSecrets(group?: string): SecretMetadata[];
|
|
75
|
+
/**
|
|
76
|
+
* List all agents and their group memberships.
|
|
77
|
+
*/
|
|
78
|
+
listAgents(): Array<{
|
|
79
|
+
name: string;
|
|
80
|
+
groups: string[];
|
|
81
|
+
}>;
|
|
82
|
+
/** Access the parsed manifest. */
|
|
83
|
+
get manifest(): Manifest;
|
|
84
|
+
/**
|
|
85
|
+
* Reload the manifest from disk (e.g. after a pull).
|
|
86
|
+
*/
|
|
87
|
+
reload(): void;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=vault.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsDD;;;;;;;;;;;GAWG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,SAAS,CAAW;gBAEhB,OAAO,EAAE,YAAY;IAkBjC;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAkCrB;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAeZ;;;;;;;OAOG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B9C;;;;;OAKG;IACH,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE;IAwB7C;;OAEG;IACH,UAAU,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAIvD,kCAAkC;IAClC,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED;;OAEG;IACH,MAAM,IAAI,IAAI;CAGf"}
|
package/dist/vault.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main Vault class — read-only agent access to secrets.
|
|
3
|
+
*
|
|
4
|
+
* The Vault handles key loading, Git synchronization, and age decryption.
|
|
5
|
+
* Decrypted material is never written to disk — it stays in memory only.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
8
|
+
import { execSync } from "node:child_process";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join, resolve } from "node:path";
|
|
11
|
+
import * as age from "age-encryption";
|
|
12
|
+
import { VaultNotFoundError, SecretNotFoundError, NotAuthorizedError, } from "./errors.js";
|
|
13
|
+
import { Manifest } from "./manifest.js";
|
|
14
|
+
import { parseMetadataFile } from "./metadata.js";
|
|
15
|
+
/**
|
|
16
|
+
* Extract the AGE-SECRET-KEY line from key file contents.
|
|
17
|
+
* Key files may contain comments (lines starting with #) and blank lines.
|
|
18
|
+
*/
|
|
19
|
+
function extractIdentity(content) {
|
|
20
|
+
const lines = content.split("\n");
|
|
21
|
+
for (const line of lines) {
|
|
22
|
+
const trimmed = line.trim();
|
|
23
|
+
if (trimmed.startsWith("AGE-SECRET-KEY-")) {
|
|
24
|
+
return trimmed;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
throw new VaultNotFoundError("No valid age identity found. Expected a line starting with AGE-SECRET-KEY-.");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convert a secret path like "stripe/api-key" to a relative file path.
|
|
31
|
+
* "stripe/api-key" becomes "stripe/api-key.enc" (or .meta).
|
|
32
|
+
*/
|
|
33
|
+
function toFilePath(secretPath, suffix) {
|
|
34
|
+
const parts = secretPath.split("/");
|
|
35
|
+
if (parts.length < 2) {
|
|
36
|
+
return parts[0] + suffix;
|
|
37
|
+
}
|
|
38
|
+
const dir = parts.slice(0, -1).join("/");
|
|
39
|
+
const file = parts[parts.length - 1] + suffix;
|
|
40
|
+
return join(dir, file);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Recursively find all files matching a glob suffix in a directory.
|
|
44
|
+
*/
|
|
45
|
+
function findFiles(dir, suffix) {
|
|
46
|
+
const results = [];
|
|
47
|
+
if (!existsSync(dir)) {
|
|
48
|
+
return results;
|
|
49
|
+
}
|
|
50
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const fullPath = join(dir, entry.name);
|
|
53
|
+
if (entry.isDirectory()) {
|
|
54
|
+
results.push(...findFiles(fullPath, suffix));
|
|
55
|
+
}
|
|
56
|
+
else if (entry.name.endsWith(suffix)) {
|
|
57
|
+
results.push(fullPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Read-only vault for agents to retrieve secrets.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const vault = new Vault({
|
|
68
|
+
* repoPath: "/path/to/repo",
|
|
69
|
+
* keyPath: "~/.agent-vault/agents/my-agent.key",
|
|
70
|
+
* });
|
|
71
|
+
* const apiKey = await vault.get("stripe/api-key");
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export class Vault {
|
|
75
|
+
_repoPath;
|
|
76
|
+
_vaultDir;
|
|
77
|
+
_identity;
|
|
78
|
+
_autoPull;
|
|
79
|
+
_manifest;
|
|
80
|
+
constructor(options) {
|
|
81
|
+
this._repoPath = resolve(options.repoPath);
|
|
82
|
+
this._vaultDir = join(this._repoPath, ".agent-vault");
|
|
83
|
+
this._autoPull = options.autoPull ?? true;
|
|
84
|
+
if (!existsSync(this._vaultDir) || !statSync(this._vaultDir).isDirectory()) {
|
|
85
|
+
throw new VaultNotFoundError(`No vault found at ${this._repoPath}. Run 'agent-vault init' first.`);
|
|
86
|
+
}
|
|
87
|
+
// Load identity (private key)
|
|
88
|
+
this._identity = this._loadIdentity(options);
|
|
89
|
+
// Load manifest
|
|
90
|
+
this._manifest = Manifest.load(join(this._vaultDir, "manifest.yaml"));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Resolve and load the age identity (private key).
|
|
94
|
+
*
|
|
95
|
+
* Priority:
|
|
96
|
+
* 1. keyStr option (raw string)
|
|
97
|
+
* 2. keyPath option (file path)
|
|
98
|
+
* 3. AGENT_VAULT_KEY env var (raw string)
|
|
99
|
+
* 4. ~/.agent-vault/owner.key (default file)
|
|
100
|
+
*/
|
|
101
|
+
_loadIdentity(options) {
|
|
102
|
+
if (options.keyStr) {
|
|
103
|
+
return extractIdentity(options.keyStr);
|
|
104
|
+
}
|
|
105
|
+
if (options.keyPath) {
|
|
106
|
+
const resolvedPath = options.keyPath.startsWith("~")
|
|
107
|
+
? join(homedir(), options.keyPath.slice(1))
|
|
108
|
+
: resolve(options.keyPath);
|
|
109
|
+
if (!existsSync(resolvedPath)) {
|
|
110
|
+
throw new VaultNotFoundError(`Key file not found: ${resolvedPath}`);
|
|
111
|
+
}
|
|
112
|
+
return extractIdentity(readFileSync(resolvedPath, "utf-8"));
|
|
113
|
+
}
|
|
114
|
+
const envKey = process.env.AGENT_VAULT_KEY;
|
|
115
|
+
if (envKey) {
|
|
116
|
+
return extractIdentity(envKey);
|
|
117
|
+
}
|
|
118
|
+
const defaultKeyPath = join(homedir(), ".agent-vault", "owner.key");
|
|
119
|
+
if (existsSync(defaultKeyPath)) {
|
|
120
|
+
return extractIdentity(readFileSync(defaultKeyPath, "utf-8"));
|
|
121
|
+
}
|
|
122
|
+
throw new VaultNotFoundError("No key provided. Pass keyPath, keyStr, set the AGENT_VAULT_KEY " +
|
|
123
|
+
"environment variable, or ensure ~/.agent-vault/owner.key exists.");
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Pull latest changes from the Git remote (best-effort).
|
|
127
|
+
*
|
|
128
|
+
* Failures are logged to stderr but do not throw. The vault continues
|
|
129
|
+
* with whatever local state is available.
|
|
130
|
+
*/
|
|
131
|
+
pull() {
|
|
132
|
+
try {
|
|
133
|
+
execSync("git pull", {
|
|
134
|
+
cwd: this._repoPath,
|
|
135
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
136
|
+
timeout: 30_000,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
141
|
+
process.stderr.write(`Warning: git pull failed (continuing with local state): ${message}\n`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Retrieve and decrypt a secret.
|
|
146
|
+
*
|
|
147
|
+
* @param secretPath - The secret path (e.g. "stripe/api-key").
|
|
148
|
+
* @returns The decrypted plaintext value.
|
|
149
|
+
* @throws SecretNotFoundError if the secret does not exist.
|
|
150
|
+
* @throws NotAuthorizedError if the key cannot decrypt the secret.
|
|
151
|
+
*/
|
|
152
|
+
async get(secretPath) {
|
|
153
|
+
if (this._autoPull) {
|
|
154
|
+
this.pull();
|
|
155
|
+
}
|
|
156
|
+
const encPath = join(this._vaultDir, "secrets", toFilePath(secretPath, ".enc"));
|
|
157
|
+
if (!existsSync(encPath)) {
|
|
158
|
+
throw new SecretNotFoundError(`Secret not found: ${secretPath}`);
|
|
159
|
+
}
|
|
160
|
+
const ciphertext = readFileSync(encPath);
|
|
161
|
+
try {
|
|
162
|
+
const d = new age.Decrypter();
|
|
163
|
+
d.addIdentity(this._identity);
|
|
164
|
+
const plaintext = await d.decrypt(ciphertext, "text");
|
|
165
|
+
return plaintext;
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
throw new NotAuthorizedError(`Cannot decrypt '${secretPath}': ${err instanceof Error ? err.message : String(err)}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* List secret metadata without decrypting.
|
|
173
|
+
*
|
|
174
|
+
* @param group - Optional group name to filter by.
|
|
175
|
+
* @returns Array of SecretMetadata objects.
|
|
176
|
+
*/
|
|
177
|
+
listSecrets(group) {
|
|
178
|
+
const secretsDir = join(this._vaultDir, "secrets");
|
|
179
|
+
if (!existsSync(secretsDir)) {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
const metaFiles = findFiles(secretsDir, ".meta").sort();
|
|
183
|
+
const results = [];
|
|
184
|
+
for (const metaPath of metaFiles) {
|
|
185
|
+
try {
|
|
186
|
+
const meta = parseMetadataFile(metaPath);
|
|
187
|
+
if (group === undefined || meta.group === group) {
|
|
188
|
+
results.push(meta);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Skip unparseable metadata files
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return results;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* List all agents and their group memberships.
|
|
200
|
+
*/
|
|
201
|
+
listAgents() {
|
|
202
|
+
return this._manifest.listAgents();
|
|
203
|
+
}
|
|
204
|
+
/** Access the parsed manifest. */
|
|
205
|
+
get manifest() {
|
|
206
|
+
return this._manifest;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Reload the manifest from disk (e.g. after a pull).
|
|
210
|
+
*/
|
|
211
|
+
reload() {
|
|
212
|
+
this._manifest = Manifest.load(join(this._vaultDir, "manifest.yaml"));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAC;AACtC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAuB,MAAM,eAAe,CAAC;AAiBvE;;;GAGG;AACH,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC1C,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IACD,MAAM,IAAI,kBAAkB,CAC1B,6EAA6E,CAC9E,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,UAAkB,EAAE,MAAc;IACpD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAC3B,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IAC9C,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,GAAW,EAAE,MAAc;IAC5C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,KAAK;IACC,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,SAAS,CAAU;IAC5B,SAAS,CAAW;IAE5B,YAAY,OAAqB;QAC/B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QACtD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;QAE1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAC3E,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,IAAI,CAAC,SAAS,iCAAiC,CACrE,CAAC;QACJ,CAAC;QAED,8BAA8B;QAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAE7C,gBAAgB;QAChB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;IACxE,CAAC;IAED;;;;;;;;OAQG;IACK,aAAa,CAAC,OAAqB;QACzC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBAClD,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC3C,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAE7B,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,kBAAkB,CAC1B,uBAAuB,YAAY,EAAE,CACtC,CAAC;YACJ,CAAC;YACD,OAAO,eAAe,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QAC3C,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;QACpE,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,OAAO,eAAe,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,IAAI,kBAAkB,CAC1B,iEAAiE;YACjE,kEAAkE,CACnE,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,IAAI;QACF,IAAI,CAAC;YACH,QAAQ,CAAC,UAAU,EAAE;gBACnB,GAAG,EAAE,IAAI,CAAC,SAAS;gBACnB,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;gBACnC,OAAO,EAAE,MAAM;aAChB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,2DAA2D,OAAO,IAAI,CACvE,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,GAAG,CAAC,UAAkB;QAC1B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAClB,IAAI,CAAC,SAAS,EACd,SAAS,EACT,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,CAC/B,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,mBAAmB,CAAC,qBAAqB,UAAU,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QAEzC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAC9B,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACtD,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,kBAAkB,CAC1B,mBAAmB,UAAU,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACtF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,KAAc;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACxD,MAAM,OAAO,GAAqB,EAAE,CAAC;QAErC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBACzC,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;oBAChD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,kCAAkC;gBAClC,SAAS;YACX,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC;IAED,kCAAkC;IAClC,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;IACxE,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ewimsatt/agent-vault",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Zero-trust credential manager for AI agents — Node.js SDK",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"test": "vitest",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"age-encryption": "^0.2.4",
|
|
21
|
+
"js-yaml": "^4.1.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/js-yaml": "^4.0.9",
|
|
25
|
+
"@types/node": "^22.0.0",
|
|
26
|
+
"typescript": "^5.7.0",
|
|
27
|
+
"vitest": "^3.0.0"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20.0.0"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/ewimsatt/agent-vault.git",
|
|
35
|
+
"directory": "node-sdk"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/ewimsatt/agent-vault",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/ewimsatt/agent-vault/issues"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"security",
|
|
43
|
+
"encryption",
|
|
44
|
+
"credentials",
|
|
45
|
+
"ai-agents",
|
|
46
|
+
"age",
|
|
47
|
+
"mcp",
|
|
48
|
+
"zero-trust",
|
|
49
|
+
"secret-management"
|
|
50
|
+
],
|
|
51
|
+
"author": "agent-vault contributors"
|
|
52
|
+
}
|