aquaman-core 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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -0
  3. package/dist/audit/index.d.ts +5 -0
  4. package/dist/audit/index.d.ts.map +1 -0
  5. package/dist/audit/index.js +5 -0
  6. package/dist/audit/index.js.map +1 -0
  7. package/dist/audit/logger.d.ts +48 -0
  8. package/dist/audit/logger.d.ts.map +1 -0
  9. package/dist/audit/logger.js +237 -0
  10. package/dist/audit/logger.js.map +1 -0
  11. package/dist/credentials/backends/onepassword.d.ts +38 -0
  12. package/dist/credentials/backends/onepassword.d.ts.map +1 -0
  13. package/dist/credentials/backends/onepassword.js +218 -0
  14. package/dist/credentials/backends/onepassword.js.map +1 -0
  15. package/dist/credentials/backends/vault.d.ts +56 -0
  16. package/dist/credentials/backends/vault.d.ts.map +1 -0
  17. package/dist/credentials/backends/vault.js +206 -0
  18. package/dist/credentials/backends/vault.js.map +1 -0
  19. package/dist/credentials/index.d.ts +7 -0
  20. package/dist/credentials/index.d.ts.map +1 -0
  21. package/dist/credentials/index.js +7 -0
  22. package/dist/credentials/index.js.map +1 -0
  23. package/dist/credentials/store.d.ts +88 -0
  24. package/dist/credentials/store.d.ts.map +1 -0
  25. package/dist/credentials/store.js +221 -0
  26. package/dist/credentials/store.js.map +1 -0
  27. package/dist/index.d.ts +14 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +18 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/types.d.ts +85 -0
  32. package/dist/types.d.ts.map +1 -0
  33. package/dist/types.js +11 -0
  34. package/dist/types.js.map +1 -0
  35. package/dist/utils/config.d.ts +18 -0
  36. package/dist/utils/config.d.ts.map +1 -0
  37. package/dist/utils/config.js +115 -0
  38. package/dist/utils/config.js.map +1 -0
  39. package/dist/utils/hash.d.ts +27 -0
  40. package/dist/utils/hash.d.ts.map +1 -0
  41. package/dist/utils/hash.js +348 -0
  42. package/dist/utils/hash.js.map +1 -0
  43. package/dist/utils/index.d.ts +6 -0
  44. package/dist/utils/index.d.ts.map +1 -0
  45. package/dist/utils/index.js +6 -0
  46. package/dist/utils/index.js.map +1 -0
  47. package/package.json +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tech4242
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # aquaman-core
2
+
3
+ Core credential storage, audit logging, and crypto utilities for [aquaman](https://github.com/tech4242/aquaman).
4
+
5
+ ## What This Is
6
+
7
+ `aquaman-core` provides the foundational building blocks for credential isolation:
8
+
9
+ - **Credential backends** — Keychain (macOS), encrypted file (Linux/CI), 1Password, HashiCorp Vault
10
+ - **Audit logger** — Hash-chained (SHA-256) tamper-evident logging with WAL-based crash recovery
11
+ - **Crypto utilities** — Key derivation, AES-256-GCM encryption, hash chain verification
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install aquaman-core
17
+ ```
18
+
19
+ ## Credential Backends
20
+
21
+ | Backend | Platform | Use Case |
22
+ |---------|----------|----------|
23
+ | `keychain` | macOS | Local dev, personal machines |
24
+ | `encrypted-file` | Linux, WSL2, CI/CD | Servers without native keyring |
25
+ | `1password` | Any (via `op` CLI) | Team credential sharing |
26
+ | `vault` | Any (via HTTP API) | Enterprise secrets management |
27
+
28
+ ## Usage
29
+
30
+ ```typescript
31
+ import { createCredentialStore } from 'aquaman-core/credentials';
32
+ import { AuditLogger } from 'aquaman-core/audit';
33
+
34
+ // Create a credential store
35
+ const store = await createCredentialStore({ backend: 'keychain' });
36
+ await store.set('anthropic', 'api_key', 'sk-ant-...');
37
+ const key = await store.get('anthropic', 'api_key');
38
+
39
+ // Hash-chained audit logging
40
+ const logger = new AuditLogger({ logDir: '~/.aquaman/audit' });
41
+ await logger.log({ action: 'credential_access', service: 'anthropic' });
42
+ await logger.verify(); // Verify chain integrity
43
+ ```
44
+
45
+ ## Documentation
46
+
47
+ See the [main README](https://github.com/tech4242/aquaman#readme) for full documentation, architecture details, and configuration options.
48
+
49
+ ## License
50
+
51
+ MIT
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Audit logging module
3
+ */
4
+ export { type AuditLoggerOptions, AuditLogger, createAuditLogger } from './logger.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,KAAK,kBAAkB,EACvB,WAAW,EACX,iBAAiB,EAClB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Audit logging module
3
+ */
4
+ export { AuditLogger, createAuditLogger } from './logger.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAEL,WAAW,EACX,iBAAiB,EAClB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Hash-chained audit logger with tamper-evident storage
3
+ *
4
+ * Provides cryptographic integrity verification for audit logs.
5
+ * Note: Credential redaction is handled by OpenClaw's built-in redaction.
6
+ */
7
+ import type { AuditEntry, CredentialAccess } from '../types.js';
8
+ export interface AuditLoggerOptions {
9
+ logDir: string;
10
+ enabled?: boolean;
11
+ walEnabled?: boolean;
12
+ }
13
+ export declare class AuditLogger {
14
+ private logDir;
15
+ private currentLogPath;
16
+ private walPath;
17
+ private enabled;
18
+ private walEnabled;
19
+ private lastHash;
20
+ private entryCount;
21
+ private initialized;
22
+ constructor(options: AuditLoggerOptions);
23
+ initialize(): Promise<void>;
24
+ private recoverState;
25
+ private recoverFromWal;
26
+ logToolCall(sessionId: string, agentId: string, tool: string, params: Record<string, unknown>): Promise<AuditEntry | null>;
27
+ logToolResult(sessionId: string, agentId: string, toolCallId: string, result: unknown, error?: string): Promise<AuditEntry | null>;
28
+ logCredentialAccess(sessionId: string, agentId: string, access: CredentialAccess): Promise<AuditEntry | null>;
29
+ private writeEntry;
30
+ verifyIntegrity(): Promise<{
31
+ valid: boolean;
32
+ errors: string[];
33
+ }>;
34
+ getEntries(options?: {
35
+ limit?: number;
36
+ offset?: number;
37
+ type?: AuditEntry['type'];
38
+ sessionId?: string;
39
+ }): Promise<AuditEntry[]>;
40
+ tail(count?: number): Promise<AuditEntry[]>;
41
+ getStats(): {
42
+ entryCount: number;
43
+ lastHash: string;
44
+ };
45
+ rotateLog(): Promise<string>;
46
+ }
47
+ export declare function createAuditLogger(options: AuditLoggerOptions): AuditLogger;
48
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,UAAU,EAGV,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAAkB;gBAEzB,OAAO,EAAE,kBAAkB;IAQjC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YA2BnB,YAAY;YAyBZ,cAAc;IAwBtB,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAevB,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAcvB,mBAAmB,CACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;YAKf,UAAU;IAiDlB,eAAe,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IA4ChE,UAAU,CAAC,OAAO,CAAC,EAAE;QACzB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAyBnB,IAAI,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAKrD,QAAQ,IAAI;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAO9C,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;CAiBnC;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAE1E"}
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Hash-chained audit logger with tamper-evident storage
3
+ *
4
+ * Provides cryptographic integrity verification for audit logs.
5
+ * Note: Credential redaction is handled by OpenClaw's built-in redaction.
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import { computeChainedHash, generateId } from '../utils/hash.js';
10
+ import { expandPath } from '../utils/config.js';
11
+ const GENESIS_HASH = '0000000000000000000000000000000000000000000000000000000000000000';
12
+ export class AuditLogger {
13
+ logDir;
14
+ currentLogPath;
15
+ walPath;
16
+ enabled;
17
+ walEnabled;
18
+ lastHash = GENESIS_HASH;
19
+ entryCount = 0;
20
+ initialized = false;
21
+ constructor(options) {
22
+ this.logDir = expandPath(options.logDir);
23
+ this.currentLogPath = path.join(this.logDir, 'current.jsonl');
24
+ this.walPath = path.join(this.logDir, 'current.wal');
25
+ this.enabled = options.enabled ?? true;
26
+ this.walEnabled = options.walEnabled ?? true;
27
+ }
28
+ async initialize() {
29
+ if (this.initialized)
30
+ return;
31
+ if (!this.enabled) {
32
+ this.initialized = true;
33
+ return;
34
+ }
35
+ // Ensure directories exist
36
+ const archiveDir = path.join(this.logDir, 'archive');
37
+ const integrityDir = path.join(this.logDir, 'integrity');
38
+ fs.mkdirSync(this.logDir, { recursive: true });
39
+ fs.mkdirSync(archiveDir, { recursive: true });
40
+ fs.mkdirSync(integrityDir, { recursive: true });
41
+ // Recover state from existing log
42
+ await this.recoverState();
43
+ // Recover from WAL if present
44
+ if (this.walEnabled) {
45
+ await this.recoverFromWal();
46
+ }
47
+ this.initialized = true;
48
+ }
49
+ async recoverState() {
50
+ if (!fs.existsSync(this.currentLogPath)) {
51
+ return;
52
+ }
53
+ const content = fs.readFileSync(this.currentLogPath, 'utf-8');
54
+ const lines = content.trim().split('\n').filter(line => line.length > 0);
55
+ if (lines.length === 0) {
56
+ return;
57
+ }
58
+ this.entryCount = lines.length;
59
+ // Get the hash of the last entry
60
+ const lastLine = lines[lines.length - 1];
61
+ try {
62
+ const lastEntry = JSON.parse(lastLine);
63
+ this.lastHash = lastEntry.hash;
64
+ }
65
+ catch {
66
+ // If we can't parse the last line, start fresh with integrity warning
67
+ console.error('Warning: Could not parse last audit entry, integrity may be compromised');
68
+ }
69
+ }
70
+ async recoverFromWal() {
71
+ if (!fs.existsSync(this.walPath)) {
72
+ return;
73
+ }
74
+ const walContent = fs.readFileSync(this.walPath, 'utf-8');
75
+ const lines = walContent.trim().split('\n').filter(line => line.length > 0);
76
+ for (const line of lines) {
77
+ try {
78
+ const entry = JSON.parse(line);
79
+ // Write to main log
80
+ fs.appendFileSync(this.currentLogPath, JSON.stringify(entry) + '\n');
81
+ this.lastHash = entry.hash;
82
+ this.entryCount++;
83
+ }
84
+ catch {
85
+ console.error('Warning: Could not recover WAL entry');
86
+ }
87
+ }
88
+ // Clear WAL after recovery
89
+ fs.writeFileSync(this.walPath, '');
90
+ }
91
+ async logToolCall(sessionId, agentId, tool, params) {
92
+ if (!this.enabled)
93
+ return null;
94
+ const toolCall = {
95
+ id: generateId(),
96
+ sessionId,
97
+ agentId,
98
+ tool,
99
+ params,
100
+ timestamp: new Date()
101
+ };
102
+ return this.writeEntry('tool_call', sessionId, agentId, toolCall);
103
+ }
104
+ async logToolResult(sessionId, agentId, toolCallId, result, error) {
105
+ if (!this.enabled)
106
+ return null;
107
+ const toolResult = {
108
+ id: generateId(),
109
+ toolCallId,
110
+ result,
111
+ error,
112
+ timestamp: new Date()
113
+ };
114
+ return this.writeEntry('tool_result', sessionId, agentId, toolResult);
115
+ }
116
+ async logCredentialAccess(sessionId, agentId, access) {
117
+ if (!this.enabled)
118
+ return null;
119
+ return this.writeEntry('credential_access', sessionId, agentId, access);
120
+ }
121
+ async writeEntry(type, sessionId, agentId, data) {
122
+ if (!this.initialized) {
123
+ await this.initialize();
124
+ }
125
+ const entry = {
126
+ id: generateId(),
127
+ timestamp: new Date(),
128
+ type,
129
+ sessionId,
130
+ agentId,
131
+ data,
132
+ previousHash: this.lastHash,
133
+ hash: '' // Will be computed below
134
+ };
135
+ // Compute hash including previous hash for chain integrity
136
+ const entryData = JSON.stringify({
137
+ ...entry,
138
+ hash: undefined
139
+ });
140
+ entry.hash = computeChainedHash(entryData, this.lastHash);
141
+ const line = JSON.stringify(entry) + '\n';
142
+ // Write to WAL first (for crash recovery)
143
+ if (this.walEnabled) {
144
+ fs.appendFileSync(this.walPath, line);
145
+ }
146
+ // Write to main log
147
+ fs.appendFileSync(this.currentLogPath, line);
148
+ // Clear WAL entry after successful write
149
+ if (this.walEnabled) {
150
+ fs.writeFileSync(this.walPath, '');
151
+ }
152
+ this.lastHash = entry.hash;
153
+ this.entryCount++;
154
+ return entry;
155
+ }
156
+ async verifyIntegrity() {
157
+ const errors = [];
158
+ if (!fs.existsSync(this.currentLogPath)) {
159
+ return { valid: true, errors: [] };
160
+ }
161
+ const content = fs.readFileSync(this.currentLogPath, 'utf-8');
162
+ const lines = content.trim().split('\n').filter(line => line.length > 0);
163
+ let previousHash = GENESIS_HASH;
164
+ for (let i = 0; i < lines.length; i++) {
165
+ try {
166
+ const entry = JSON.parse(lines[i]);
167
+ // Verify previous hash reference
168
+ if (entry.previousHash !== previousHash) {
169
+ errors.push(`Entry ${i}: previousHash mismatch (expected ${previousHash}, got ${entry.previousHash})`);
170
+ }
171
+ // Verify entry hash
172
+ const entryData = JSON.stringify({
173
+ ...entry,
174
+ hash: undefined
175
+ });
176
+ const expectedHash = computeChainedHash(entryData, entry.previousHash);
177
+ if (entry.hash !== expectedHash) {
178
+ errors.push(`Entry ${i}: hash mismatch (expected ${expectedHash}, got ${entry.hash})`);
179
+ }
180
+ previousHash = entry.hash;
181
+ }
182
+ catch (parseError) {
183
+ errors.push(`Entry ${i}: failed to parse JSON`);
184
+ }
185
+ }
186
+ return {
187
+ valid: errors.length === 0,
188
+ errors
189
+ };
190
+ }
191
+ async getEntries(options) {
192
+ if (!fs.existsSync(this.currentLogPath)) {
193
+ return [];
194
+ }
195
+ const content = fs.readFileSync(this.currentLogPath, 'utf-8');
196
+ const lines = content.trim().split('\n').filter(line => line.length > 0);
197
+ let entries = lines.map(line => JSON.parse(line));
198
+ // Apply filters
199
+ if (options?.type) {
200
+ entries = entries.filter(e => e.type === options.type);
201
+ }
202
+ if (options?.sessionId) {
203
+ entries = entries.filter(e => e.sessionId === options.sessionId);
204
+ }
205
+ // Apply pagination
206
+ const offset = options?.offset ?? 0;
207
+ const limit = options?.limit ?? entries.length;
208
+ return entries.slice(offset, offset + limit);
209
+ }
210
+ async tail(count = 10) {
211
+ const entries = await this.getEntries();
212
+ return entries.slice(-count);
213
+ }
214
+ getStats() {
215
+ return {
216
+ entryCount: this.entryCount,
217
+ lastHash: this.lastHash
218
+ };
219
+ }
220
+ async rotateLog() {
221
+ if (!fs.existsSync(this.currentLogPath)) {
222
+ throw new Error('No log file to rotate');
223
+ }
224
+ const archiveDir = path.join(this.logDir, 'archive');
225
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
226
+ const archivePath = path.join(archiveDir, `audit-${timestamp}.jsonl`);
227
+ fs.renameSync(this.currentLogPath, archivePath);
228
+ // Reset state for new log
229
+ this.lastHash = GENESIS_HASH;
230
+ this.entryCount = 0;
231
+ return archivePath;
232
+ }
233
+ }
234
+ export function createAuditLogger(options) {
235
+ return new AuditLogger(options);
236
+ }
237
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 1Password credential backend using the `op` CLI
3
+ * Requires: 1Password CLI installed and signed in
4
+ */
5
+ import type { CredentialStore } from '../store.js';
6
+ export interface OnePasswordStoreOptions {
7
+ vault?: string;
8
+ account?: string;
9
+ }
10
+ export declare class OnePasswordStore implements CredentialStore {
11
+ private vault;
12
+ private account?;
13
+ private opPath;
14
+ constructor(options?: OnePasswordStoreOptions);
15
+ private validateOpCli;
16
+ private runOp;
17
+ private getItemName;
18
+ private parseItemName;
19
+ private ensureVaultExists;
20
+ get(service: string, key: string): Promise<string | null>;
21
+ set(service: string, key: string, value: string, metadata?: Record<string, string>): Promise<void>;
22
+ delete(service: string, key: string): Promise<boolean>;
23
+ list(service?: string): Promise<Array<{
24
+ service: string;
25
+ key: string;
26
+ }>>;
27
+ exists(service: string, key: string): Promise<boolean>;
28
+ /**
29
+ * Get the vault name being used
30
+ */
31
+ getVault(): string;
32
+ /**
33
+ * Check if 1Password CLI is available and signed in
34
+ */
35
+ static isAvailable(): boolean;
36
+ }
37
+ export declare function createOnePasswordStore(options?: OnePasswordStoreOptions): OnePasswordStore;
38
+ //# sourceMappingURL=onepassword.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onepassword.d.ts","sourceRoot":"","sources":["../../../src/credentials/backends/onepassword.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD,qBAAa,gBAAiB,YAAW,eAAe;IACtD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,CAAC,EAAE,uBAAuB;IAM7C,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,KAAK;IAyBb,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,iBAAiB;IAcnB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAsBzD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAsClG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBtD,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAiCxE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5D;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,OAAO;CAa9B;AAED,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,gBAAgB,CAE1F"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * 1Password credential backend using the `op` CLI
3
+ * Requires: 1Password CLI installed and signed in
4
+ */
5
+ import { spawnSync } from 'node:child_process';
6
+ const DEFAULT_VAULT = 'aquaman';
7
+ const ITEM_PREFIX = 'aquaman';
8
+ export class OnePasswordStore {
9
+ vault;
10
+ account;
11
+ opPath = null;
12
+ constructor(options) {
13
+ this.vault = options?.vault || DEFAULT_VAULT;
14
+ this.account = options?.account;
15
+ this.validateOpCli();
16
+ }
17
+ validateOpCli() {
18
+ // Check if op CLI is installed
19
+ try {
20
+ const result = spawnSync('which', ['op'], { encoding: 'utf-8' });
21
+ if (result.status !== 0) {
22
+ throw new Error('1Password CLI (op) not found. Install from: https://1password.com/downloads/command-line/');
23
+ }
24
+ this.opPath = result.stdout.trim();
25
+ }
26
+ catch {
27
+ throw new Error('1Password CLI (op) not found. Install from: https://1password.com/downloads/command-line/');
28
+ }
29
+ // Check if signed in
30
+ try {
31
+ this.runOp(['account', 'get']);
32
+ }
33
+ catch (error) {
34
+ throw new Error('Not signed in to 1Password. Run: op signin');
35
+ }
36
+ }
37
+ runOp(args, input) {
38
+ const accountArgs = this.account ? ['--account', this.account] : [];
39
+ const fullArgs = [...args, ...accountArgs];
40
+ try {
41
+ const result = spawnSync('op', fullArgs, {
42
+ encoding: 'utf-8',
43
+ input,
44
+ maxBuffer: 10 * 1024 * 1024
45
+ });
46
+ if (result.status !== 0) {
47
+ const error = result.stderr || result.stdout || 'Unknown error';
48
+ throw new Error(`op command failed: ${error}`);
49
+ }
50
+ return result.stdout;
51
+ }
52
+ catch (error) {
53
+ if (error instanceof Error && error.message.includes('op command failed')) {
54
+ throw error;
55
+ }
56
+ throw new Error(`Failed to run op command: ${error}`);
57
+ }
58
+ }
59
+ getItemName(service, key) {
60
+ return `${ITEM_PREFIX}-${service}-${key}`;
61
+ }
62
+ parseItemName(itemName) {
63
+ if (!itemName.startsWith(`${ITEM_PREFIX}-`)) {
64
+ return null;
65
+ }
66
+ const parts = itemName.slice(ITEM_PREFIX.length + 1).split('-');
67
+ if (parts.length < 2) {
68
+ return null;
69
+ }
70
+ // Handle service names with dashes by taking first part as service
71
+ const service = parts[0];
72
+ const key = parts.slice(1).join('-');
73
+ return { service, key };
74
+ }
75
+ ensureVaultExists() {
76
+ try {
77
+ this.runOp(['vault', 'get', this.vault]);
78
+ }
79
+ catch {
80
+ // Vault doesn't exist, create it
81
+ try {
82
+ this.runOp(['vault', 'create', this.vault]);
83
+ console.log(`Created 1Password vault: ${this.vault}`);
84
+ }
85
+ catch (createError) {
86
+ throw new Error(`Failed to create vault "${this.vault}": ${createError}`);
87
+ }
88
+ }
89
+ }
90
+ async get(service, key) {
91
+ const itemName = this.getItemName(service, key);
92
+ try {
93
+ const result = this.runOp([
94
+ 'item', 'get', itemName,
95
+ '--vault', this.vault,
96
+ '--fields', 'credential',
97
+ '--format', 'json'
98
+ ]);
99
+ const parsed = JSON.parse(result);
100
+ return parsed.value || null;
101
+ }
102
+ catch (error) {
103
+ // Item not found is not an error
104
+ if (error instanceof Error && error.message.includes('not found')) {
105
+ return null;
106
+ }
107
+ throw error;
108
+ }
109
+ }
110
+ async set(service, key, value, metadata) {
111
+ this.ensureVaultExists();
112
+ const itemName = this.getItemName(service, key);
113
+ const tags = [ITEM_PREFIX, service];
114
+ // Check if item already exists
115
+ const existing = await this.get(service, key);
116
+ if (existing !== null) {
117
+ // Update existing item
118
+ this.runOp([
119
+ 'item', 'edit', itemName,
120
+ '--vault', this.vault,
121
+ `credential=${value}`
122
+ ]);
123
+ }
124
+ else {
125
+ // Create new item
126
+ const createArgs = [
127
+ 'item', 'create',
128
+ '--category', 'API Credential',
129
+ '--vault', this.vault,
130
+ '--title', itemName,
131
+ `credential=${value}`,
132
+ '--tags', tags.join(',')
133
+ ];
134
+ // Add metadata as fields
135
+ if (metadata) {
136
+ for (const [k, v] of Object.entries(metadata)) {
137
+ createArgs.push(`${k}=${v}`);
138
+ }
139
+ }
140
+ this.runOp(createArgs);
141
+ }
142
+ }
143
+ async delete(service, key) {
144
+ const itemName = this.getItemName(service, key);
145
+ try {
146
+ this.runOp([
147
+ 'item', 'delete', itemName,
148
+ '--vault', this.vault
149
+ ]);
150
+ return true;
151
+ }
152
+ catch (error) {
153
+ if (error instanceof Error && error.message.includes('not found')) {
154
+ return false;
155
+ }
156
+ throw error;
157
+ }
158
+ }
159
+ async list(service) {
160
+ try {
161
+ const listArgs = [
162
+ 'item', 'list',
163
+ '--vault', this.vault,
164
+ '--tags', service ? `${ITEM_PREFIX},${service}` : ITEM_PREFIX,
165
+ '--format', 'json'
166
+ ];
167
+ const result = this.runOp(listArgs);
168
+ const items = JSON.parse(result);
169
+ const credentials = [];
170
+ for (const item of items) {
171
+ const parsed = this.parseItemName(item.title);
172
+ if (parsed) {
173
+ if (!service || parsed.service === service) {
174
+ credentials.push(parsed);
175
+ }
176
+ }
177
+ }
178
+ return credentials;
179
+ }
180
+ catch (error) {
181
+ // Vault might not exist yet
182
+ if (error instanceof Error && error.message.includes('not found')) {
183
+ return [];
184
+ }
185
+ throw error;
186
+ }
187
+ }
188
+ async exists(service, key) {
189
+ const value = await this.get(service, key);
190
+ return value !== null;
191
+ }
192
+ /**
193
+ * Get the vault name being used
194
+ */
195
+ getVault() {
196
+ return this.vault;
197
+ }
198
+ /**
199
+ * Check if 1Password CLI is available and signed in
200
+ */
201
+ static isAvailable() {
202
+ try {
203
+ const whichResult = spawnSync('which', ['op'], { encoding: 'utf-8' });
204
+ if (whichResult.status !== 0) {
205
+ return false;
206
+ }
207
+ const accountResult = spawnSync('op', ['account', 'get'], { encoding: 'utf-8' });
208
+ return accountResult.status === 0;
209
+ }
210
+ catch {
211
+ return false;
212
+ }
213
+ }
214
+ }
215
+ export function createOnePasswordStore(options) {
216
+ return new OnePasswordStore(options);
217
+ }
218
+ //# sourceMappingURL=onepassword.js.map