@elizaos/vault 2.0.0-alpha.537

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.
Files changed (62) hide show
  1. package/README.md +159 -0
  2. package/dist/audit.d.ts +14 -0
  3. package/dist/audit.d.ts.map +1 -0
  4. package/dist/audit.js +27 -0
  5. package/dist/audit.js.map +1 -0
  6. package/dist/credentials.d.ts +58 -0
  7. package/dist/credentials.d.ts.map +1 -0
  8. package/dist/credentials.js +157 -0
  9. package/dist/credentials.js.map +1 -0
  10. package/dist/crypto.d.ts +18 -0
  11. package/dist/crypto.d.ts.map +1 -0
  12. package/dist/crypto.js +67 -0
  13. package/dist/crypto.js.map +1 -0
  14. package/dist/external-credentials.d.ts +62 -0
  15. package/dist/external-credentials.d.ts.map +1 -0
  16. package/dist/external-credentials.js +335 -0
  17. package/dist/external-credentials.js.map +1 -0
  18. package/dist/index.d.ts +35 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +26 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/install.d.ts +70 -0
  23. package/dist/install.d.ts.map +1 -0
  24. package/dist/install.js +163 -0
  25. package/dist/install.js.map +1 -0
  26. package/dist/inventory.d.ts +140 -0
  27. package/dist/inventory.d.ts.map +1 -0
  28. package/dist/inventory.js +319 -0
  29. package/dist/inventory.js.map +1 -0
  30. package/dist/manager.d.ts +161 -0
  31. package/dist/manager.d.ts.map +1 -0
  32. package/dist/manager.js +466 -0
  33. package/dist/manager.js.map +1 -0
  34. package/dist/master-key.d.ts +86 -0
  35. package/dist/master-key.d.ts.map +1 -0
  36. package/dist/master-key.js +247 -0
  37. package/dist/master-key.js.map +1 -0
  38. package/dist/password-managers.d.ts +17 -0
  39. package/dist/password-managers.d.ts.map +1 -0
  40. package/dist/password-managers.js +59 -0
  41. package/dist/password-managers.js.map +1 -0
  42. package/dist/profiles.d.ts +68 -0
  43. package/dist/profiles.d.ts.map +1 -0
  44. package/dist/profiles.js +189 -0
  45. package/dist/profiles.js.map +1 -0
  46. package/dist/store.d.ts +22 -0
  47. package/dist/store.d.ts.map +1 -0
  48. package/dist/store.js +137 -0
  49. package/dist/store.js.map +1 -0
  50. package/dist/testing.d.ts +32 -0
  51. package/dist/testing.d.ts.map +1 -0
  52. package/dist/testing.js +70 -0
  53. package/dist/testing.js.map +1 -0
  54. package/dist/types.d.ts +56 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +12 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/vault.d.ts +77 -0
  59. package/dist/vault.d.ts.map +1 -0
  60. package/dist/vault.js +269 -0
  61. package/dist/vault.js.map +1 -0
  62. package/package.json +59 -0
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Profile resolution + per-context routing on top of `Vault`.
3
+ *
4
+ * Two layers:
5
+ *
6
+ * 1. Per-key active profile.
7
+ * A key K can have multiple named profiles (e.g. work, personal,
8
+ * throwaway). Each profile's value lives at `K.profile.<profileId>`;
9
+ * the meta blob (`_meta.K`) tracks the profile list and which one
10
+ * is currently active for bare reads. When no meta is present the
11
+ * legacy storage path is used (the value lives at K itself).
12
+ *
13
+ * 2. Per-context routing rules.
14
+ * A user can declare "for OPENROUTER_API_KEY, when agentId=X use the
15
+ * work profile". Rules are walked in order; the first match wins.
16
+ * Falls back to the key's `activeProfile`, then to the global
17
+ * `defaultProfile`, then to the legacy bare-key value.
18
+ *
19
+ * The vault stays dumb: every read goes through `Vault.get/has`. The
20
+ * only routing logic lives here so the vault contract is unchanged.
21
+ */
22
+ import { META_PREFIX, profileStorageKey, readEntryMeta, ROUTING_KEY, } from "./inventory.js";
23
+ const EMPTY_ROUTING = { rules: [] };
24
+ // ── Public API ─────────────────────────────────────────────────────
25
+ /**
26
+ * Resolve `key` against (a) per-context routing rules, (b) the key's
27
+ * `activeProfile`, (c) the global `defaultProfile`, then (d) the bare
28
+ * key value.
29
+ *
30
+ * Throws when none of the above resolves to a stored value — callers
31
+ * decide how to surface the miss (e.g. inventory routes return 404,
32
+ * runtime callers fall back to env var).
33
+ */
34
+ export async function resolveActiveValue(vault, key, ctx) {
35
+ const meta = await readEntryMeta(vault, key);
36
+ const profiles = meta?.profiles ?? [];
37
+ const hasProfiles = profiles.length > 0;
38
+ if (hasProfiles) {
39
+ const routing = await readRoutingConfig(vault);
40
+ const ruled = pickRule(routing.rules, key, ctx);
41
+ const candidateOrder = [
42
+ ruled?.profileId,
43
+ meta?.activeProfile,
44
+ routing.defaultProfile,
45
+ ].filter((v) => typeof v === "string" && v.length > 0);
46
+ const allowed = new Set(profiles.map((p) => p.id));
47
+ for (const candidate of candidateOrder) {
48
+ if (!allowed.has(candidate))
49
+ continue;
50
+ const profileKey = profileStorageKey(key, candidate);
51
+ if (await vault.has(profileKey)) {
52
+ return vault.get(profileKey);
53
+ }
54
+ }
55
+ // Fall through to the bare key — preserves backwards compat for
56
+ // keys whose `meta.profiles` exists but the chosen profile blob
57
+ // is missing (a partial migration). This is intentional: the
58
+ // bare key is the legacy "default" location.
59
+ }
60
+ return vault.get(key);
61
+ }
62
+ /**
63
+ * Read the routing config blob from the vault. Missing or malformed
64
+ * entries return `EMPTY_ROUTING` — routing is best-effort overlay,
65
+ * not a load-bearing contract.
66
+ */
67
+ export async function readRoutingConfig(vault) {
68
+ if (!(await vault.has(ROUTING_KEY)))
69
+ return EMPTY_ROUTING;
70
+ const raw = await vault.get(ROUTING_KEY);
71
+ return parseRoutingConfig(raw);
72
+ }
73
+ /** Persist the routing config blob. Caller-validated input. */
74
+ export async function writeRoutingConfig(vault, config) {
75
+ const normalized = normalizeRoutingConfig(config);
76
+ await vault.set(ROUTING_KEY, JSON.stringify(normalized));
77
+ }
78
+ // ── Internals ───────────────────────────────────────────────────────
79
+ function pickRule(rules, key, ctx) {
80
+ if (!ctx)
81
+ return null;
82
+ for (const rule of rules) {
83
+ if (rule.keyPattern !== key)
84
+ continue;
85
+ if (matchesScope(rule.scope, ctx))
86
+ return rule;
87
+ }
88
+ return null;
89
+ }
90
+ function matchesScope(scope, ctx) {
91
+ if (scope.kind === "agent") {
92
+ return (typeof scope.agentId === "string" &&
93
+ typeof ctx.agentId === "string" &&
94
+ scope.agentId === ctx.agentId);
95
+ }
96
+ if (scope.kind === "app") {
97
+ return (typeof scope.appName === "string" &&
98
+ typeof ctx.appName === "string" &&
99
+ scope.appName === ctx.appName);
100
+ }
101
+ if (scope.kind === "skill") {
102
+ return (typeof scope.skillId === "string" &&
103
+ typeof ctx.skillId === "string" &&
104
+ scope.skillId === ctx.skillId);
105
+ }
106
+ return false;
107
+ }
108
+ function parseRoutingConfig(raw) {
109
+ const parsed = JSON.parse(raw);
110
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
111
+ return EMPTY_ROUTING;
112
+ }
113
+ const obj = parsed;
114
+ const rules = [];
115
+ if (Array.isArray(obj.rules)) {
116
+ for (const r of obj.rules) {
117
+ const normalized = normalizeRule(r);
118
+ if (normalized)
119
+ rules.push(normalized);
120
+ }
121
+ }
122
+ const out = {
123
+ rules,
124
+ ...(typeof obj.defaultProfile === "string" && obj.defaultProfile.length > 0
125
+ ? { defaultProfile: obj.defaultProfile }
126
+ : {}),
127
+ };
128
+ return out;
129
+ }
130
+ function normalizeRoutingConfig(config) {
131
+ const rules = [];
132
+ for (const r of config.rules ?? []) {
133
+ const normalized = normalizeRule(r);
134
+ if (normalized)
135
+ rules.push(normalized);
136
+ }
137
+ return {
138
+ rules,
139
+ ...(typeof config.defaultProfile === "string" &&
140
+ config.defaultProfile.length > 0
141
+ ? { defaultProfile: config.defaultProfile }
142
+ : {}),
143
+ };
144
+ }
145
+ function normalizeRule(r) {
146
+ if (!r || typeof r !== "object")
147
+ return null;
148
+ const rec = r;
149
+ if (typeof rec.keyPattern !== "string" || rec.keyPattern.length === 0) {
150
+ return null;
151
+ }
152
+ if (rec.keyPattern.startsWith(META_PREFIX) ||
153
+ rec.keyPattern === ROUTING_KEY) {
154
+ return null; // never route an internal key
155
+ }
156
+ if (typeof rec.profileId !== "string" || rec.profileId.length === 0) {
157
+ return null;
158
+ }
159
+ const scope = rec.scope;
160
+ if (!scope || typeof scope !== "object")
161
+ return null;
162
+ const scopeRec = scope;
163
+ const kind = scopeRec.kind;
164
+ if (kind !== "agent" && kind !== "app" && kind !== "skill")
165
+ return null;
166
+ if (kind === "agent" && typeof scopeRec.agentId === "string") {
167
+ return {
168
+ keyPattern: rec.keyPattern,
169
+ scope: { kind: "agent", agentId: scopeRec.agentId },
170
+ profileId: rec.profileId,
171
+ };
172
+ }
173
+ if (kind === "app" && typeof scopeRec.appName === "string") {
174
+ return {
175
+ keyPattern: rec.keyPattern,
176
+ scope: { kind: "app", appName: scopeRec.appName },
177
+ profileId: rec.profileId,
178
+ };
179
+ }
180
+ if (kind === "skill" && typeof scopeRec.skillId === "string") {
181
+ return {
182
+ keyPattern: rec.keyPattern,
183
+ scope: { kind: "skill", skillId: scopeRec.skillId },
184
+ profileId: rec.profileId,
185
+ };
186
+ }
187
+ return null;
188
+ }
189
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { StoredEntry } from "./types.js";
2
+ /**
3
+ * On-disk representation of the vault.
4
+ *
5
+ * One file: `<workDir>/vault.json` mode 0600. Atomic writes via temp +
6
+ * rename. No nested structures, no migration scaffolding, no version
7
+ * gates beyond a single integer.
8
+ */
9
+ export declare const STORE_VERSION = 1;
10
+ export interface StoreData {
11
+ readonly version: number;
12
+ readonly entries: Readonly<Record<string, StoredEntry>>;
13
+ }
14
+ export declare class StoreFormatError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ export declare function emptyStore(): StoreData;
18
+ export declare function readStore(path: string): Promise<StoreData>;
19
+ export declare function writeStore(path: string, data: StoreData): Promise<void>;
20
+ export declare function setEntry(data: StoreData, key: string, entry: StoredEntry): StoreData;
21
+ export declare function removeEntry(data: StoreData, key: string): StoreData;
22
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;GAMG;AAEH,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CACzD;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,UAAU,IAAI,SAAS,CAEtC;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAiBhE;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB7E;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,WAAW,GACjB,SAAS,CAKX;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAKnE"}
package/dist/store.js ADDED
@@ -0,0 +1,137 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { promises as fs } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ /**
5
+ * On-disk representation of the vault.
6
+ *
7
+ * One file: `<workDir>/vault.json` mode 0600. Atomic writes via temp +
8
+ * rename. No nested structures, no migration scaffolding, no version
9
+ * gates beyond a single integer.
10
+ */
11
+ export const STORE_VERSION = 1;
12
+ export class StoreFormatError extends Error {
13
+ constructor(message) {
14
+ super(`vault store: ${message}`);
15
+ this.name = "StoreFormatError";
16
+ }
17
+ }
18
+ export function emptyStore() {
19
+ return { version: STORE_VERSION, entries: {} };
20
+ }
21
+ export async function readStore(path) {
22
+ let raw;
23
+ try {
24
+ raw = await fs.readFile(path, "utf8");
25
+ }
26
+ catch (err) {
27
+ if (err.code === "ENOENT")
28
+ return emptyStore();
29
+ throw err;
30
+ }
31
+ let parsed;
32
+ try {
33
+ parsed = JSON.parse(raw);
34
+ }
35
+ catch (err) {
36
+ throw new StoreFormatError(`parse error: ${err instanceof Error ? err.message : String(err)}`);
37
+ }
38
+ return validateShape(parsed);
39
+ }
40
+ export async function writeStore(path, data) {
41
+ await fs.mkdir(dirname(path), { recursive: true });
42
+ // Per-write tmp filename so two VaultImpl instances cannot collide on the
43
+ // same `${path}.tmp` and silently clobber each other's writes. pid + 8
44
+ // random bytes is overkill for collision avoidance but keeps the cost
45
+ // negligible vs the rest of the write.
46
+ const tmp = `${path}.tmp.${process.pid}.${randomBytes(8).toString("hex")}`;
47
+ const body = `${JSON.stringify(data, null, 2)}\n`;
48
+ // mode 0o600 on the tmp file, before rename. POSIX rename preserves mode,
49
+ // so the final file inherits 0o600 with no observable window where it sat
50
+ // at the umask default.
51
+ await fs.writeFile(tmp, body, { mode: 0o600, flag: "w" });
52
+ try {
53
+ await fs.rename(tmp, path);
54
+ }
55
+ catch (renameErr) {
56
+ // rename failure (cross-device, EROFS, ENOSPC) leaves the tmp file
57
+ // behind. Best-effort cleanup so future writes aren't blocked by stale
58
+ // junk under the same per-pid prefix.
59
+ await fs.rm(tmp, { force: true }).catch(() => { });
60
+ throw renameErr;
61
+ }
62
+ }
63
+ export function setEntry(data, key, entry) {
64
+ return {
65
+ version: data.version,
66
+ entries: { ...data.entries, [key]: entry },
67
+ };
68
+ }
69
+ export function removeEntry(data, key) {
70
+ if (!(key in data.entries))
71
+ return data;
72
+ const next = { ...data.entries };
73
+ delete next[key];
74
+ return { version: data.version, entries: next };
75
+ }
76
+ function validateShape(parsed) {
77
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
78
+ throw new StoreFormatError("root must be an object");
79
+ }
80
+ const root = parsed;
81
+ if (typeof root.version !== "number") {
82
+ throw new StoreFormatError("version must be a number");
83
+ }
84
+ const version = root.version;
85
+ if (version > STORE_VERSION) {
86
+ throw new StoreFormatError(`version ${version} is newer than supported (${STORE_VERSION})`);
87
+ }
88
+ if (!root.entries ||
89
+ typeof root.entries !== "object" ||
90
+ Array.isArray(root.entries)) {
91
+ throw new StoreFormatError("entries must be an object");
92
+ }
93
+ const entriesRaw = root.entries;
94
+ const entries = {};
95
+ for (const [key, value] of Object.entries(entriesRaw)) {
96
+ entries[key] = validateEntry(key, value);
97
+ }
98
+ return { version: STORE_VERSION, entries };
99
+ }
100
+ function validateEntry(key, raw) {
101
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
102
+ throw new StoreFormatError(`entry ${key}: must be an object`);
103
+ }
104
+ const e = raw;
105
+ if (typeof e.lastModified !== "number") {
106
+ throw new StoreFormatError(`entry ${key}: lastModified must be a number`);
107
+ }
108
+ const lastModified = e.lastModified;
109
+ if (e.kind === "value") {
110
+ if (typeof e.value !== "string") {
111
+ throw new StoreFormatError(`entry ${key}: value must be a string`);
112
+ }
113
+ return { kind: "value", value: e.value, lastModified };
114
+ }
115
+ if (e.kind === "secret") {
116
+ if (typeof e.ciphertext !== "string" || e.ciphertext.length === 0) {
117
+ throw new StoreFormatError(`entry ${key}: missing ciphertext`);
118
+ }
119
+ return { kind: "secret", ciphertext: e.ciphertext, lastModified };
120
+ }
121
+ if (e.kind === "reference") {
122
+ if (e.source !== "1password" && e.source !== "protonpass") {
123
+ throw new StoreFormatError(`entry ${key}: invalid reference source`);
124
+ }
125
+ if (typeof e.path !== "string" || e.path.length === 0) {
126
+ throw new StoreFormatError(`entry ${key}: missing reference path`);
127
+ }
128
+ return {
129
+ kind: "reference",
130
+ source: e.source,
131
+ path: e.path,
132
+ lastModified,
133
+ };
134
+ }
135
+ throw new StoreFormatError(`entry ${key}: unknown kind ${JSON.stringify(e.kind)}`);
136
+ }
137
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Testing utilities for @elizaos/vault.
3
+ *
4
+ * import { createTestVault } from "@elizaos/vault/testing";
5
+ *
6
+ * const test = await createTestVault({ "ui.theme": "dark" });
7
+ * await test.vault.set("openrouter.apiKey", "k", { sensitive: true });
8
+ * await test.dispose();
9
+ */
10
+ import { type Vault } from "./vault.js";
11
+ import type { AuditRecord } from "./types.js";
12
+ export interface TestVault {
13
+ readonly vault: Vault;
14
+ readonly storePath: string;
15
+ readonly auditLogPath: string;
16
+ /** All audit entries written so far. */
17
+ getAuditRecords(): Promise<readonly AuditRecord[]>;
18
+ /** Truncate the audit log between assertion phases. */
19
+ clearAuditLog(): Promise<void>;
20
+ /** Cleanup. Removes the temp directory. */
21
+ dispose(): Promise<void>;
22
+ }
23
+ export interface CreateTestVaultOptions {
24
+ /** Pre-seed non-sensitive values. */
25
+ readonly values?: Readonly<Record<string, string>>;
26
+ /** Pre-seed sensitive values (encrypted as if production). */
27
+ readonly secrets?: Readonly<Record<string, string>>;
28
+ /** Override the temp dir (default: mkdtemp + auto-cleanup). */
29
+ readonly workDir?: string;
30
+ }
31
+ export declare function createTestVault(opts?: CreateTestVaultOptions): Promise<TestVault>;
32
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,wCAAwC;IACxC,eAAe,IAAI,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;IACnD,uDAAuD;IACvD,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,2CAA2C;IAC3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,eAAe,CACnC,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,SAAS,CAAC,CAkDpB"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Testing utilities for @elizaos/vault.
3
+ *
4
+ * import { createTestVault } from "@elizaos/vault/testing";
5
+ *
6
+ * const test = await createTestVault({ "ui.theme": "dark" });
7
+ * await test.vault.set("openrouter.apiKey", "k", { sensitive: true });
8
+ * await test.dispose();
9
+ */
10
+ import { promises as fs } from "node:fs";
11
+ import { tmpdir } from "node:os";
12
+ import { join } from "node:path";
13
+ import { createVault } from "./vault.js";
14
+ import { generateMasterKey } from "./crypto.js";
15
+ import { inMemoryMasterKey } from "./master-key.js";
16
+ export async function createTestVault(opts = {}) {
17
+ const ownsWorkDir = !opts.workDir;
18
+ const workDir = opts.workDir ?? (await fs.mkdtemp(join(tmpdir(), "eliza-vault-")));
19
+ const storePath = join(workDir, "vault.json");
20
+ const auditLogPath = join(workDir, "audit", "vault.jsonl");
21
+ const vault = createVault({
22
+ workDir,
23
+ masterKey: inMemoryMasterKey(generateMasterKey()),
24
+ });
25
+ if (opts.values) {
26
+ for (const [key, value] of Object.entries(opts.values)) {
27
+ await vault.set(key, value);
28
+ }
29
+ }
30
+ if (opts.secrets) {
31
+ for (const [key, value] of Object.entries(opts.secrets)) {
32
+ await vault.set(key, value, { sensitive: true });
33
+ }
34
+ }
35
+ return {
36
+ vault,
37
+ storePath,
38
+ auditLogPath,
39
+ async getAuditRecords() {
40
+ let raw;
41
+ try {
42
+ raw = await fs.readFile(auditLogPath, "utf8");
43
+ }
44
+ catch (err) {
45
+ if (err.code === "ENOENT")
46
+ return [];
47
+ throw err;
48
+ }
49
+ return raw
50
+ .split("\n")
51
+ .filter((l) => l.trim().length > 0)
52
+ .map((l) => JSON.parse(l));
53
+ },
54
+ async clearAuditLog() {
55
+ try {
56
+ await fs.writeFile(auditLogPath, "", { mode: 0o600 });
57
+ }
58
+ catch (err) {
59
+ if (err.code !== "ENOENT")
60
+ throw err;
61
+ }
62
+ },
63
+ async dispose() {
64
+ if (ownsWorkDir) {
65
+ await fs.rm(workDir, { recursive: true, force: true });
66
+ }
67
+ },
68
+ };
69
+ }
70
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Public types for @elizaos/vault.
3
+ *
4
+ * The vault holds two kinds of things keyed by a string:
5
+ * - sensitive values (API keys, tokens, private keys) — encrypted at rest
6
+ * - non-sensitive values (config: theme, model preferences, flags) — plaintext
7
+ *
8
+ * The same `set/get/has/describe/list/remove` API serves both; the caller
9
+ * declares sensitivity at write time. Reads don't need to know.
10
+ */
11
+ /** Reference to a value held in an external password manager. */
12
+ export interface PasswordManagerReference {
13
+ readonly source: "1password" | "protonpass";
14
+ /** Vendor-specific path. e.g., "Personal/OpenRouter/api-key" for op://. */
15
+ readonly path: string;
16
+ }
17
+ /** Internal storage shape. Consumers use `describe()` to inspect, never see this directly. */
18
+ export type StoredEntry = {
19
+ readonly kind: "value";
20
+ readonly value: string;
21
+ readonly lastModified: number;
22
+ } | {
23
+ readonly kind: "secret";
24
+ /** AES-256-GCM ciphertext: `v1:nonce:tag:ct` (all base64). */
25
+ readonly ciphertext: string;
26
+ readonly lastModified: number;
27
+ } | {
28
+ readonly kind: "reference";
29
+ readonly source: PasswordManagerReference["source"];
30
+ readonly path: string;
31
+ readonly lastModified: number;
32
+ };
33
+ export interface VaultDescriptor {
34
+ readonly key: string;
35
+ readonly source: "file" | "keychain-encrypted" | "1password" | "protonpass";
36
+ readonly sensitive: boolean;
37
+ readonly lastModified: number;
38
+ }
39
+ export interface VaultStats {
40
+ readonly total: number;
41
+ readonly sensitive: number;
42
+ readonly nonSensitive: number;
43
+ readonly references: number;
44
+ }
45
+ export interface AuditRecord {
46
+ readonly ts: number;
47
+ readonly action: "set" | "setReference" | "get" | "reveal" | "remove";
48
+ readonly key: string;
49
+ /** Caller-supplied identifier for who's asking. Optional. */
50
+ readonly caller?: string;
51
+ }
52
+ export interface VaultLogger {
53
+ readonly warn: (msg: string, ctx?: unknown) => void;
54
+ readonly error: (msg: string, ctx?: unknown) => void;
55
+ }
56
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,iEAAiE;AACjE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAAC;IAC5C,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,8FAA8F;AAC9F,MAAM,MAAM,WAAW,GACnB;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEN,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,GAAG,WAAW,GAAG,YAAY,CAAC;IAC5E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACtE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACtD"}
package/dist/types.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Public types for @elizaos/vault.
3
+ *
4
+ * The vault holds two kinds of things keyed by a string:
5
+ * - sensitive values (API keys, tokens, private keys) — encrypted at rest
6
+ * - non-sensitive values (config: theme, model preferences, flags) — plaintext
7
+ *
8
+ * The same `set/get/has/describe/list/remove` API serves both; the caller
9
+ * declares sensitivity at write time. Reads don't need to know.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,77 @@
1
+ import { type MasterKeyResolver } from "./master-key.js";
2
+ import type { PasswordManagerReference, VaultDescriptor, VaultLogger, VaultStats } from "./types.js";
3
+ /**
4
+ * Simple secrets/config vault.
5
+ *
6
+ * One API serves both sensitive credentials and non-sensitive config:
7
+ * await vault.set("openrouter.apiKey", "sk-or-...", { sensitive: true });
8
+ * await vault.set("ui.theme", "dark");
9
+ * const v = await vault.get("openrouter.apiKey");
10
+ *
11
+ * Sensitive values are AES-256-GCM encrypted with the vault key as AAD;
12
+ * the master key lives in the OS keychain. Non-sensitive values are
13
+ * stored plaintext in `vault.json` (mode 0600). References to external
14
+ * password managers (1Password, Proton Pass) are first-class — the
15
+ * vault stores only the reference and resolves at use time.
16
+ */
17
+ export interface Vault {
18
+ /** Store a value. Sensitive values are encrypted at rest. */
19
+ set(key: string, value: string, opts?: SetOptions): Promise<void>;
20
+ /**
21
+ * Store a reference to a password-manager item. The actual value
22
+ * lives there, never copied to disk by this vault.
23
+ */
24
+ setReference(key: string, ref: PasswordManagerReference): Promise<void>;
25
+ /** Read a value. Resolves through the password manager if needed. */
26
+ get(key: string): Promise<string>;
27
+ /**
28
+ * Read with audit trail. Use this for "show / reveal" UI affordances
29
+ * — every reveal is recorded with the caller id so users can see who
30
+ * read what.
31
+ */
32
+ reveal(key: string, caller?: string): Promise<string>;
33
+ /** Existence check. Does NOT reveal the value. */
34
+ has(key: string): Promise<boolean>;
35
+ /** Remove. Idempotent. */
36
+ remove(key: string): Promise<void>;
37
+ /** List keys. Optional prefix filter. Does NOT reveal values. */
38
+ list(prefix?: string): Promise<readonly string[]>;
39
+ /** Describe a key without revealing it. */
40
+ describe(key: string): Promise<VaultDescriptor | null>;
41
+ /** Aggregate counts. */
42
+ stats(): Promise<VaultStats>;
43
+ }
44
+ export interface SetOptions {
45
+ /** True if the value is a credential. Sensitive values are encrypted. */
46
+ readonly sensitive?: boolean;
47
+ /** Optional caller id for the audit log. */
48
+ readonly caller?: string;
49
+ }
50
+ export interface CreateVaultOptions {
51
+ /**
52
+ * Working directory. Resolution order (first non-empty wins):
53
+ *
54
+ * 1. `opts.workDir` — explicit caller override (tests, embedded use).
55
+ * 2. `$ELIZA_STATE_DIR` — Eliza's state-dir override.
56
+ * 3. `$ELIZA_STATE_DIR` — elizaOS-compatible state-dir override.
57
+ * 4. `~/$ELIZA_NAMESPACE` with a leading dot (`~/.eliza` by default).
58
+ *
59
+ * The vault writes `vault.json` and `audit/vault.jsonl` inside the
60
+ * resolved directory.
61
+ */
62
+ readonly workDir?: string;
63
+ /**
64
+ * Master key resolver. Default: OS keychain via `@napi-rs/keyring`.
65
+ * Override with `inMemoryMasterKey(buffer)` for tests.
66
+ */
67
+ readonly masterKey?: MasterKeyResolver;
68
+ /** Optional logger for non-fatal warnings. */
69
+ readonly logger?: VaultLogger;
70
+ }
71
+ export declare function createVault(opts?: CreateVaultOptions): Vault;
72
+ export declare class VaultMissError extends Error {
73
+ readonly key: string;
74
+ constructor(key: string);
75
+ }
76
+ export { emptyStore } from "./store.js";
77
+ //# sourceMappingURL=vault.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAW3E,OAAO,KAAK,EAEV,wBAAwB,EAExB,eAAe,EACf,WAAW,EACX,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,KAAK;IACpB,6DAA6D;IAC7D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;OAGG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE,qEAAqE;IACrE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAElC;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEtD,kDAAkD;IAClD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnC,0BAA0B;IAC1B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,iEAAiE;IACjE,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAElD,2CAA2C;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAEvD,wBAAwB;IACxB,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IACvC,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,KAAK,CAShE;AAwMD,qBAAa,cAAe,SAAQ,KAAK;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM;gBAAX,GAAG,EAAE,MAAM;CAIjC;AAgBD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}