@clawmasons/credential-service 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 ADDED
@@ -0,0 +1,7 @@
1
+ # @clawmasons/credential-service
2
+
3
+ Credential resolution and distribution service for Mason
4
+
5
+ ## More Information
6
+
7
+ This package is part of the [Mason](https://github.com/clawmasons/mason) monorepo. See the [README](https://github.com/clawmasons/mason/blob/main/README.md) for full documentation.
@@ -0,0 +1,36 @@
1
+ import Database from "better-sqlite3";
2
+ export interface CredentialAuditEntry {
3
+ id: string;
4
+ timestamp: string;
5
+ agent_id: string;
6
+ role: string;
7
+ session_id: string;
8
+ credential_key: string;
9
+ outcome: "granted" | "denied" | "error";
10
+ deny_reason: string | null;
11
+ source: string | null;
12
+ }
13
+ export interface CredentialAuditFilters {
14
+ agent_id?: string;
15
+ credential_key?: string;
16
+ outcome?: string;
17
+ session_id?: string;
18
+ limit?: number;
19
+ }
20
+ /**
21
+ * Open the credential audit database and ensure the table exists.
22
+ */
23
+ export declare function openCredentialDatabase(dbPath?: string): Database.Database;
24
+ /**
25
+ * Insert a credential audit entry.
26
+ */
27
+ export declare function insertCredentialAudit(db: Database.Database, entry: CredentialAuditEntry): void;
28
+ /**
29
+ * Query credential audit entries with optional filters.
30
+ */
31
+ export declare function queryCredentialAudit(db: Database.Database, filters?: CredentialAuditFilters): CredentialAuditEntry[];
32
+ /**
33
+ * Generate a unique ID for audit entries.
34
+ */
35
+ export declare function generateAuditId(): string;
36
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAQtC,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAsBD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,GAAE,MAAwB,GAC/B,QAAQ,CAAC,QAAQ,CASnB;AAID;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,oBAAoB,GAC1B,IAAI,CAUN;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,oBAAoB,EAAE,CAiCxB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
package/dist/audit.js ADDED
@@ -0,0 +1,88 @@
1
+ import Database from "better-sqlite3";
2
+ import { mkdirSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ import { randomUUID } from "node:crypto";
6
+ // ── Schema ─────────────────────────────────────────────────────────────
7
+ const CREATE_CREDENTIAL_AUDIT = `
8
+ CREATE TABLE IF NOT EXISTS credential_audit (
9
+ id TEXT PRIMARY KEY,
10
+ timestamp TEXT NOT NULL,
11
+ agent_id TEXT NOT NULL,
12
+ role TEXT NOT NULL,
13
+ session_id TEXT NOT NULL,
14
+ credential_key TEXT NOT NULL,
15
+ outcome TEXT NOT NULL,
16
+ deny_reason TEXT,
17
+ source TEXT
18
+ )`;
19
+ // ── Database ───────────────────────────────────────────────────────────
20
+ const DEFAULT_DB_PATH = process.env.CREDENTIAL_DB_PATH
21
+ ?? join(homedir(), ".chapter", "data", "chapter.db");
22
+ /**
23
+ * Open the credential audit database and ensure the table exists.
24
+ */
25
+ export function openCredentialDatabase(dbPath = DEFAULT_DB_PATH) {
26
+ if (dbPath !== ":memory:") {
27
+ mkdirSync(dirname(dbPath), { recursive: true });
28
+ }
29
+ const db = new Database(dbPath);
30
+ db.pragma("journal_mode = WAL");
31
+ db.exec(CREATE_CREDENTIAL_AUDIT);
32
+ return db;
33
+ }
34
+ // ── Operations ─────────────────────────────────────────────────────────
35
+ /**
36
+ * Insert a credential audit entry.
37
+ */
38
+ export function insertCredentialAudit(db, entry) {
39
+ const stmt = db.prepare(`
40
+ INSERT INTO credential_audit (id, timestamp, agent_id, role, session_id, credential_key, outcome, deny_reason, source)
41
+ VALUES (@id, @timestamp, @agent_id, @role, @session_id, @credential_key, @outcome, @deny_reason, @source)
42
+ `);
43
+ stmt.run({
44
+ ...entry,
45
+ deny_reason: entry.deny_reason ?? null,
46
+ source: entry.source ?? null,
47
+ });
48
+ }
49
+ /**
50
+ * Query credential audit entries with optional filters.
51
+ */
52
+ export function queryCredentialAudit(db, filters) {
53
+ const conditions = [];
54
+ const params = {};
55
+ if (filters?.agent_id) {
56
+ conditions.push("agent_id = @agent_id");
57
+ params.agent_id = filters.agent_id;
58
+ }
59
+ if (filters?.credential_key) {
60
+ conditions.push("credential_key = @credential_key");
61
+ params.credential_key = filters.credential_key;
62
+ }
63
+ if (filters?.outcome) {
64
+ conditions.push("outcome = @outcome");
65
+ params.outcome = filters.outcome;
66
+ }
67
+ if (filters?.session_id) {
68
+ conditions.push("session_id = @session_id");
69
+ params.session_id = filters.session_id;
70
+ }
71
+ let sql = "SELECT * FROM credential_audit";
72
+ if (conditions.length > 0) {
73
+ sql += " WHERE " + conditions.join(" AND ");
74
+ }
75
+ sql += " ORDER BY timestamp DESC";
76
+ if (filters?.limit) {
77
+ sql += " LIMIT @limit";
78
+ params.limit = filters.limit;
79
+ }
80
+ return db.prepare(sql).all(params);
81
+ }
82
+ /**
83
+ * Generate a unique ID for audit entries.
84
+ */
85
+ export function generateAuditId() {
86
+ return randomUUID();
87
+ }
88
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import { CredentialResolver } from "./resolver.js";
3
+ import { CredentialService } from "./service.js";
4
+ import { CredentialWSClient } from "./ws-client.js";
5
+ async function main() {
6
+ const proxyUrl = process.env.CREDENTIAL_PROXY_URL;
7
+ const proxyToken = process.env.CREDENTIAL_PROXY_TOKEN;
8
+ const dbPath = process.env.CREDENTIAL_DB_PATH;
9
+ const envFilePath = process.env.CREDENTIAL_ENV_FILE;
10
+ const keychainService = process.env.CREDENTIAL_KEYCHAIN_SERVICE ?? "clawmasons";
11
+ if (!proxyUrl) {
12
+ console.error("CREDENTIAL_PROXY_URL is required");
13
+ process.exit(1);
14
+ }
15
+ if (!proxyToken) {
16
+ console.error("CREDENTIAL_PROXY_TOKEN is required");
17
+ process.exit(1);
18
+ }
19
+ const resolver = new CredentialResolver({
20
+ envFilePath,
21
+ keychainService,
22
+ });
23
+ const service = new CredentialService({ dbPath, envFilePath, keychainService }, resolver);
24
+ // Apply session overrides if provided (from ACP proxy)
25
+ const sessionOverridesJson = process.env.CREDENTIAL_SESSION_OVERRIDES;
26
+ if (sessionOverridesJson) {
27
+ try {
28
+ const overrides = JSON.parse(sessionOverridesJson);
29
+ service.setSessionOverrides(overrides);
30
+ console.log(`[credential-service] Loaded ${Object.keys(overrides).length} session credential override(s).`);
31
+ }
32
+ catch (err) {
33
+ console.error("[credential-service] Invalid CREDENTIAL_SESSION_OVERRIDES JSON:", err);
34
+ service.close();
35
+ process.exit(1);
36
+ }
37
+ }
38
+ const client = new CredentialWSClient(service);
39
+ console.log(`[credential-service] Connecting to proxy at ${proxyUrl}...`);
40
+ try {
41
+ await client.connect(proxyUrl, proxyToken);
42
+ console.log("[credential-service] Connected to proxy.");
43
+ }
44
+ catch (err) {
45
+ console.error("[credential-service] Failed to connect to proxy:", err);
46
+ service.close();
47
+ process.exit(1);
48
+ }
49
+ // Handle shutdown
50
+ const shutdown = () => {
51
+ console.log("[credential-service] Shutting down...");
52
+ client.disconnect();
53
+ service.close();
54
+ process.exit(0);
55
+ };
56
+ process.on("SIGINT", shutdown);
57
+ process.on("SIGTERM", shutdown);
58
+ }
59
+ main().catch((err) => {
60
+ console.error("[credential-service] Fatal error:", err);
61
+ process.exit(1);
62
+ });
63
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Parse a .env file into a key-value record.
3
+ *
4
+ * Handles:
5
+ * - KEY=VALUE lines
6
+ * - Blank lines and comments (lines starting with #)
7
+ * - Single-quoted, double-quoted, and unquoted values
8
+ * - Inline comments after unquoted values
9
+ *
10
+ * Copied from @clawmasons/proxy to avoid cross-package dependency.
11
+ */
12
+ export declare function loadEnvFile(filePath: string): Record<string, string>;
13
+ //# sourceMappingURL=env-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.d.ts","sourceRoot":"","sources":["../src/env-file.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAwCpE"}
@@ -0,0 +1,47 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ /**
3
+ * Parse a .env file into a key-value record.
4
+ *
5
+ * Handles:
6
+ * - KEY=VALUE lines
7
+ * - Blank lines and comments (lines starting with #)
8
+ * - Single-quoted, double-quoted, and unquoted values
9
+ * - Inline comments after unquoted values
10
+ *
11
+ * Copied from @clawmasons/proxy to avoid cross-package dependency.
12
+ */
13
+ export function loadEnvFile(filePath) {
14
+ if (!existsSync(filePath)) {
15
+ return {};
16
+ }
17
+ const content = readFileSync(filePath, "utf-8");
18
+ const result = {};
19
+ for (const line of content.split("\n")) {
20
+ const trimmed = line.trim();
21
+ // Skip blank lines and comments
22
+ if (!trimmed || trimmed.startsWith("#"))
23
+ continue;
24
+ const eqIndex = trimmed.indexOf("=");
25
+ if (eqIndex === -1)
26
+ continue;
27
+ const key = trimmed.slice(0, eqIndex).trim();
28
+ if (!key)
29
+ continue;
30
+ let value = trimmed.slice(eqIndex + 1).trim();
31
+ // Handle quoted values
32
+ if ((value.startsWith('"') && value.endsWith('"')) ||
33
+ (value.startsWith("'") && value.endsWith("'"))) {
34
+ value = value.slice(1, -1);
35
+ }
36
+ else {
37
+ // Strip inline comments for unquoted values
38
+ const commentIndex = value.indexOf(" #");
39
+ if (commentIndex !== -1) {
40
+ value = value.slice(0, commentIndex).trim();
41
+ }
42
+ }
43
+ result[key] = value;
44
+ }
45
+ return result;
46
+ }
47
+ //# sourceMappingURL=env-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.js","sourceRoot":"","sources":["../src/env-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,gCAAgC;QAChC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAElD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,CAAC,CAAC;YAAE,SAAS;QAE7B,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,IAAI,CAAC,GAAG;YAAE,SAAS;QAEnB,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAE9C,uBAAuB;QACvB,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,4CAA4C;YAC5C,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;gBACxB,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { CredentialResolver, type CredentialResolverConfig, type ResolveResult, type ResolveSuccess, type ResolveError, } from "./resolver.js";
2
+ export { loadEnvFile } from "./env-file.js";
3
+ export { credentialRequestSchema, credentialResponseSchema, credentialSuccessSchema, credentialErrorSchema, credentialServiceConfigSchema, type CredentialRequest, type CredentialResponse, type CredentialServiceConfig, } from "./schemas.js";
4
+ export { CredentialService } from "./service.js";
5
+ export { CredentialWSClient, type CredentialWSClientOptions } from "./ws-client.js";
6
+ export { openCredentialDatabase, insertCredentialAudit, queryCredentialAudit, generateAuditId, type CredentialAuditEntry, type CredentialAuditFilters, } from "./audit.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAGpF,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ // Resolver (from CHANGE 2)
2
+ export { CredentialResolver, } from "./resolver.js";
3
+ export { loadEnvFile } from "./env-file.js";
4
+ // Schemas
5
+ export { credentialRequestSchema, credentialResponseSchema, credentialSuccessSchema, credentialErrorSchema, credentialServiceConfigSchema, } from "./schemas.js";
6
+ // Service (SDK mode)
7
+ export { CredentialService } from "./service.js";
8
+ // WebSocket client
9
+ export { CredentialWSClient } from "./ws-client.js";
10
+ // Audit
11
+ export { openCredentialDatabase, insertCredentialAudit, queryCredentialAudit, generateAuditId, } from "./audit.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,OAAO,EACL,kBAAkB,GAKnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,UAAU;AACV,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,GAI9B,MAAM,cAAc,CAAC;AAEtB,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAkC,MAAM,gBAAgB,CAAC;AAEpF,QAAQ;AACR,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,GAGhB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Query macOS Keychain for a credential value by service and account.
3
+ *
4
+ * Uses `security find-generic-password` to look up the value.
5
+ * Returns `undefined` if the key is not found or on any error.
6
+ */
7
+ export declare function queryKeychain(service: string, account: string): Promise<string | undefined>;
8
+ /**
9
+ * Query macOS Keychain for a credential value by service name only.
10
+ *
11
+ * Uses `security find-generic-password -s <service> -w` without an account.
12
+ * Used for system credentials like Claude Code that store under a service name.
13
+ * Returns `undefined` if not found or on any error.
14
+ */
15
+ export declare function queryKeychainByService(service: string): Promise<string | undefined>;
16
+ //# sourceMappingURL=keychain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain.d.ts","sourceRoot":"","sources":["../src/keychain.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoB7B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoB7B"}
@@ -0,0 +1,49 @@
1
+ import { execFile } from "node:child_process";
2
+ /**
3
+ * Query macOS Keychain for a credential value by service and account.
4
+ *
5
+ * Uses `security find-generic-password` to look up the value.
6
+ * Returns `undefined` if the key is not found or on any error.
7
+ */
8
+ export function queryKeychain(service, account) {
9
+ return new Promise((resolve) => {
10
+ execFile("security", ["find-generic-password", "-s", service, "-a", account, "-w"], { timeout: 5000 }, (error, stdout) => {
11
+ if (error) {
12
+ resolve(undefined);
13
+ return;
14
+ }
15
+ const value = stdout.trim();
16
+ if (value) {
17
+ resolve(value);
18
+ }
19
+ else {
20
+ resolve(undefined);
21
+ }
22
+ });
23
+ });
24
+ }
25
+ /**
26
+ * Query macOS Keychain for a credential value by service name only.
27
+ *
28
+ * Uses `security find-generic-password -s <service> -w` without an account.
29
+ * Used for system credentials like Claude Code that store under a service name.
30
+ * Returns `undefined` if not found or on any error.
31
+ */
32
+ export function queryKeychainByService(service) {
33
+ return new Promise((resolve) => {
34
+ execFile("security", ["find-generic-password", "-s", service, "-w"], { timeout: 5000 }, (error, stdout) => {
35
+ if (error) {
36
+ resolve(undefined);
37
+ return;
38
+ }
39
+ const value = stdout.trim();
40
+ if (value) {
41
+ resolve(value);
42
+ }
43
+ else {
44
+ resolve(undefined);
45
+ }
46
+ });
47
+ });
48
+ }
49
+ //# sourceMappingURL=keychain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain.js","sourceRoot":"","sources":["../src/keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,OAAe;IAEf,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CACN,UAAU,EACV,CAAC,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAC7D,EAAE,OAAO,EAAE,IAAI,EAAE,EACjB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAChB,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,SAAS,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,SAAS,CAAC,CAAC;YACrB,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAe;IAEf,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CACN,UAAU,EACV,CAAC,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAC9C,EAAE,OAAO,EAAE,IAAI,EAAE,EACjB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAChB,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,SAAS,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,SAAS,CAAC,CAAC;YACrB,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,72 @@
1
+ /** Successful credential resolution. */
2
+ export interface ResolveSuccess {
3
+ value: string;
4
+ source: "env" | "keychain" | "dotenv" | "session";
5
+ }
6
+ /** Failed credential resolution. */
7
+ export interface ResolveError {
8
+ error: string;
9
+ code: "NOT_FOUND" | "ACCESS_DENIED";
10
+ sourcesAttempted: string[];
11
+ }
12
+ /** Result of a credential resolution attempt. */
13
+ export type ResolveResult = ResolveSuccess | ResolveError;
14
+ /** Configuration for the credential resolver. */
15
+ export interface CredentialResolverConfig {
16
+ /** Path to the .env file. Defaults to ".env" in cwd. */
17
+ envFilePath?: string;
18
+ /** macOS Keychain service name. Defaults to "clawmasons". */
19
+ keychainService?: string;
20
+ }
21
+ /**
22
+ * Resolves credential values from multiple sources in priority order:
23
+ * 0. Session overrides (set via setSessionOverrides, used by ACP proxy)
24
+ * 1. Security key allowlist (for security.* keys — keychain or fallback file)
25
+ * 2. Environment variables (process.env)
26
+ * 3. macOS Keychain (darwin only)
27
+ * 4. .env file
28
+ */
29
+ export declare class CredentialResolver {
30
+ private readonly envFilePath;
31
+ private readonly keychainService;
32
+ private dotenvCache;
33
+ private sessionOverrides;
34
+ constructor(config?: CredentialResolverConfig);
35
+ /**
36
+ * Set session-scoped credential overrides.
37
+ *
38
+ * Session overrides take highest priority during resolution,
39
+ * checked before env, keychain, and dotenv sources. Used by the
40
+ * ACP proxy to inject credentials extracted from ACP client configs.
41
+ */
42
+ setSessionOverrides(overrides: Record<string, string>): void;
43
+ /**
44
+ * Clear all session-scoped credential overrides.
45
+ */
46
+ clearSessionOverrides(): void;
47
+ /**
48
+ * Resolve a credential key from available sources.
49
+ *
50
+ * Checks sources in priority order:
51
+ * session overrides → security.* allowlist → env → keychain → dotenv.
52
+ *
53
+ * Returns the value and source on success, or an error with
54
+ * the list of sources attempted on failure.
55
+ */
56
+ resolve(key: string): Promise<ResolveResult>;
57
+ /**
58
+ * Resolve a security.* prefixed credential key.
59
+ *
60
+ * Only keys in SECURITY_KEY_ALLOWLIST are permitted.
61
+ * On macOS: queries the keychain using the mapped service name.
62
+ * On other platforms: reads the fallback file contents.
63
+ */
64
+ private resolveSecurityKey;
65
+ /** Check process environment variables. */
66
+ private resolveFromEnv;
67
+ /** Query macOS Keychain via `security find-generic-password`. */
68
+ private resolveFromKeychain;
69
+ /** Look up the key in the parsed .env file. */
70
+ private resolveFromDotenv;
71
+ }
72
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAIA,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;CACnD;AAED,oCAAoC;AACpC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,WAAW,GAAG,eAAe,CAAC;IACpC,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,iDAAiD;AACjD,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,YAAY,CAAC;AAE1D,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACvC,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAaD;;;;;;;GAOG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,WAAW,CAAuC;IAC1D,OAAO,CAAC,gBAAgB,CAA8B;gBAE1C,MAAM,GAAE,wBAA6B;IAKjD;;;;;;OAMG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAI5D;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAI7B;;;;;;;;OAQG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA4ClD;;;;;;OAMG;YACW,kBAAkB;IAuChC,2CAA2C;IAC3C,OAAO,CAAC,cAAc;IAQtB,iEAAiE;IACjE,OAAO,CAAC,mBAAmB;IAI3B,+CAA+C;IAC/C,OAAO,CAAC,iBAAiB;CAU1B"}
@@ -0,0 +1,159 @@
1
+ import * as fs from "node:fs";
2
+ import { loadEnvFile } from "./env-file.js";
3
+ import { queryKeychain, queryKeychainByService } from "./keychain.js";
4
+ /**
5
+ * Allowlisted security.* credential keys and their keychain service mappings.
6
+ *
7
+ * Only keys in this map can be resolved via the security.* prefix.
8
+ * Any other security.* key is rejected with ACCESS_DENIED.
9
+ *
10
+ * Currently empty — reserved for future security-sensitive credentials
11
+ * that require keychain lookup rather than plain env var resolution.
12
+ */
13
+ const SECURITY_KEY_ALLOWLIST = {};
14
+ /**
15
+ * Resolves credential values from multiple sources in priority order:
16
+ * 0. Session overrides (set via setSessionOverrides, used by ACP proxy)
17
+ * 1. Security key allowlist (for security.* keys — keychain or fallback file)
18
+ * 2. Environment variables (process.env)
19
+ * 3. macOS Keychain (darwin only)
20
+ * 4. .env file
21
+ */
22
+ export class CredentialResolver {
23
+ envFilePath;
24
+ keychainService;
25
+ dotenvCache = null;
26
+ sessionOverrides = {};
27
+ constructor(config = {}) {
28
+ this.envFilePath = config.envFilePath ?? ".env";
29
+ this.keychainService = config.keychainService ?? "clawmasons";
30
+ }
31
+ /**
32
+ * Set session-scoped credential overrides.
33
+ *
34
+ * Session overrides take highest priority during resolution,
35
+ * checked before env, keychain, and dotenv sources. Used by the
36
+ * ACP proxy to inject credentials extracted from ACP client configs.
37
+ */
38
+ setSessionOverrides(overrides) {
39
+ this.sessionOverrides = { ...overrides };
40
+ }
41
+ /**
42
+ * Clear all session-scoped credential overrides.
43
+ */
44
+ clearSessionOverrides() {
45
+ this.sessionOverrides = {};
46
+ }
47
+ /**
48
+ * Resolve a credential key from available sources.
49
+ *
50
+ * Checks sources in priority order:
51
+ * session overrides → security.* allowlist → env → keychain → dotenv.
52
+ *
53
+ * Returns the value and source on success, or an error with
54
+ * the list of sources attempted on failure.
55
+ */
56
+ async resolve(key) {
57
+ // 0. Session overrides (highest priority)
58
+ const sessionValue = this.sessionOverrides[key];
59
+ if (sessionValue !== undefined) {
60
+ return { value: sessionValue, source: "session" };
61
+ }
62
+ // 1. Security key handling (security.* prefix)
63
+ if (key.startsWith("security.")) {
64
+ return this.resolveSecurityKey(key);
65
+ }
66
+ const sourcesAttempted = [];
67
+ // 2. Environment variables
68
+ sourcesAttempted.push("env");
69
+ const envValue = this.resolveFromEnv(key);
70
+ if (envValue !== undefined) {
71
+ return { value: envValue, source: "env" };
72
+ }
73
+ // 3. macOS Keychain (skipped on non-macOS)
74
+ if (process.platform === "darwin") {
75
+ sourcesAttempted.push("keychain");
76
+ const keychainValue = await this.resolveFromKeychain(key);
77
+ if (keychainValue !== undefined) {
78
+ return { value: keychainValue, source: "keychain" };
79
+ }
80
+ }
81
+ // 4. .env file
82
+ sourcesAttempted.push("dotenv");
83
+ const dotenvValue = this.resolveFromDotenv(key);
84
+ if (dotenvValue !== undefined) {
85
+ return { value: dotenvValue, source: "dotenv" };
86
+ }
87
+ return {
88
+ error: `Credential "${key}" not found in any source`,
89
+ code: "NOT_FOUND",
90
+ sourcesAttempted,
91
+ };
92
+ }
93
+ /**
94
+ * Resolve a security.* prefixed credential key.
95
+ *
96
+ * Only keys in SECURITY_KEY_ALLOWLIST are permitted.
97
+ * On macOS: queries the keychain using the mapped service name.
98
+ * On other platforms: reads the fallback file contents.
99
+ */
100
+ async resolveSecurityKey(key) {
101
+ const mapping = SECURITY_KEY_ALLOWLIST[key];
102
+ if (!mapping) {
103
+ return {
104
+ error: `Security key "${key}" is not in the allowlist`,
105
+ code: "ACCESS_DENIED",
106
+ sourcesAttempted: ["security-allowlist"],
107
+ };
108
+ }
109
+ const sourcesAttempted = [];
110
+ if (process.platform === "darwin") {
111
+ // macOS: query keychain by service name
112
+ sourcesAttempted.push("keychain");
113
+ const value = await queryKeychainByService(mapping.keychainService);
114
+ if (value !== undefined) {
115
+ return { value, source: "keychain" };
116
+ }
117
+ }
118
+ // Fallback: read from file
119
+ sourcesAttempted.push("file");
120
+ try {
121
+ const value = fs.readFileSync(mapping.fallbackFile, "utf-8");
122
+ if (value.trim()) {
123
+ return { value: value.trim(), source: "dotenv" };
124
+ }
125
+ }
126
+ catch {
127
+ // File not found or unreadable
128
+ }
129
+ return {
130
+ error: `Credential "${key}" not found in any source`,
131
+ code: "NOT_FOUND",
132
+ sourcesAttempted,
133
+ };
134
+ }
135
+ /** Check process environment variables. */
136
+ resolveFromEnv(key) {
137
+ const value = process.env[key];
138
+ if (value !== undefined && value !== "") {
139
+ return value;
140
+ }
141
+ return undefined;
142
+ }
143
+ /** Query macOS Keychain via `security find-generic-password`. */
144
+ resolveFromKeychain(key) {
145
+ return queryKeychain(this.keychainService, key);
146
+ }
147
+ /** Look up the key in the parsed .env file. */
148
+ resolveFromDotenv(key) {
149
+ if (this.dotenvCache === null) {
150
+ this.dotenvCache = loadEnvFile(this.envFilePath);
151
+ }
152
+ const value = this.dotenvCache[key];
153
+ if (value !== undefined) {
154
+ return value;
155
+ }
156
+ return undefined;
157
+ }
158
+ }
159
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ import { z } from "zod";
2
+ export declare const credentialRequestSchema: z.ZodObject<{
3
+ /** Unique request ID for correlating request/response over WebSocket. */
4
+ id: z.ZodString;
5
+ /** The credential key being requested. */
6
+ key: z.ZodString;
7
+ /** The requesting agent's slug. */
8
+ agentId: z.ZodString;
9
+ /** The agent's role slug. */
10
+ role: z.ZodString;
11
+ /** The session identifier. */
12
+ sessionId: z.ZodString;
13
+ /** The agent's full list of declared credential keys (populated by proxy). */
14
+ declaredCredentials: z.ZodArray<z.ZodString, "many">;
15
+ /** ISO 8601 timestamp (Phase 2 signing). */
16
+ timestamp: z.ZodOptional<z.ZodString>;
17
+ }, "strip", z.ZodTypeAny, {
18
+ id: string;
19
+ key: string;
20
+ agentId: string;
21
+ role: string;
22
+ sessionId: string;
23
+ declaredCredentials: string[];
24
+ timestamp?: string | undefined;
25
+ }, {
26
+ id: string;
27
+ key: string;
28
+ agentId: string;
29
+ role: string;
30
+ sessionId: string;
31
+ declaredCredentials: string[];
32
+ timestamp?: string | undefined;
33
+ }>;
34
+ export type CredentialRequest = z.infer<typeof credentialRequestSchema>;
35
+ export declare const credentialSuccessSchema: z.ZodObject<{
36
+ id: z.ZodString;
37
+ key: z.ZodString;
38
+ value: z.ZodString;
39
+ source: z.ZodEnum<["env", "keychain", "dotenv", "session"]>;
40
+ }, "strip", z.ZodTypeAny, {
41
+ value: string;
42
+ source: "env" | "keychain" | "dotenv" | "session";
43
+ id: string;
44
+ key: string;
45
+ }, {
46
+ value: string;
47
+ source: "env" | "keychain" | "dotenv" | "session";
48
+ id: string;
49
+ key: string;
50
+ }>;
51
+ export declare const credentialErrorSchema: z.ZodObject<{
52
+ id: z.ZodString;
53
+ key: z.ZodString;
54
+ error: z.ZodString;
55
+ code: z.ZodEnum<["NOT_FOUND", "ACCESS_DENIED", "INVALID_SESSION"]>;
56
+ }, "strip", z.ZodTypeAny, {
57
+ error: string;
58
+ code: "NOT_FOUND" | "ACCESS_DENIED" | "INVALID_SESSION";
59
+ id: string;
60
+ key: string;
61
+ }, {
62
+ error: string;
63
+ code: "NOT_FOUND" | "ACCESS_DENIED" | "INVALID_SESSION";
64
+ id: string;
65
+ key: string;
66
+ }>;
67
+ export declare const credentialResponseSchema: z.ZodUnion<[z.ZodObject<{
68
+ id: z.ZodString;
69
+ key: z.ZodString;
70
+ value: z.ZodString;
71
+ source: z.ZodEnum<["env", "keychain", "dotenv", "session"]>;
72
+ }, "strip", z.ZodTypeAny, {
73
+ value: string;
74
+ source: "env" | "keychain" | "dotenv" | "session";
75
+ id: string;
76
+ key: string;
77
+ }, {
78
+ value: string;
79
+ source: "env" | "keychain" | "dotenv" | "session";
80
+ id: string;
81
+ key: string;
82
+ }>, z.ZodObject<{
83
+ id: z.ZodString;
84
+ key: z.ZodString;
85
+ error: z.ZodString;
86
+ code: z.ZodEnum<["NOT_FOUND", "ACCESS_DENIED", "INVALID_SESSION"]>;
87
+ }, "strip", z.ZodTypeAny, {
88
+ error: string;
89
+ code: "NOT_FOUND" | "ACCESS_DENIED" | "INVALID_SESSION";
90
+ id: string;
91
+ key: string;
92
+ }, {
93
+ error: string;
94
+ code: "NOT_FOUND" | "ACCESS_DENIED" | "INVALID_SESSION";
95
+ id: string;
96
+ key: string;
97
+ }>]>;
98
+ export type CredentialResponse = z.infer<typeof credentialResponseSchema>;
99
+ export declare const credentialServiceConfigSchema: z.ZodObject<{
100
+ /** Path to the SQLite database. Defaults to ~/.chapter/data/chapter.db. */
101
+ dbPath: z.ZodOptional<z.ZodString>;
102
+ /** Path to the .env file for dotenv credential resolution. */
103
+ envFilePath: z.ZodOptional<z.ZodString>;
104
+ /** macOS Keychain service name. */
105
+ keychainService: z.ZodDefault<z.ZodString>;
106
+ }, "strip", z.ZodTypeAny, {
107
+ keychainService: string;
108
+ dbPath?: string | undefined;
109
+ envFilePath?: string | undefined;
110
+ }, {
111
+ dbPath?: string | undefined;
112
+ envFilePath?: string | undefined;
113
+ keychainService?: string | undefined;
114
+ }>;
115
+ export type CredentialServiceConfig = z.infer<typeof credentialServiceConfigSchema>;
116
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,uBAAuB;IAClC,yEAAyE;;IAEzE,0CAA0C;;IAE1C,mCAAmC;;IAEnC,6BAA6B;;IAE7B,8BAA8B;;IAE9B,8EAA8E;;IAE9E,4CAA4C;;;;;;;;;;;;;;;;;;EAE5C,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;EAKlC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;EAKhC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E,eAAO,MAAM,6BAA6B;IACxC,2EAA2E;;IAE3E,8DAA8D;;IAE9D,mCAAmC;;;;;;;;;;EAEnC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { z } from "zod";
2
+ // ── Credential Request ──────────────────────────────────────────────────
3
+ export const credentialRequestSchema = z.object({
4
+ /** Unique request ID for correlating request/response over WebSocket. */
5
+ id: z.string(),
6
+ /** The credential key being requested. */
7
+ key: z.string(),
8
+ /** The requesting agent's slug. */
9
+ agentId: z.string(),
10
+ /** The agent's role slug. */
11
+ role: z.string(),
12
+ /** The session identifier. */
13
+ sessionId: z.string(),
14
+ /** The agent's full list of declared credential keys (populated by proxy). */
15
+ declaredCredentials: z.array(z.string()),
16
+ /** ISO 8601 timestamp (Phase 2 signing). */
17
+ timestamp: z.string().optional(),
18
+ });
19
+ // ── Credential Response ─────────────────────────────────────────────────
20
+ export const credentialSuccessSchema = z.object({
21
+ id: z.string(),
22
+ key: z.string(),
23
+ value: z.string(),
24
+ source: z.enum(["env", "keychain", "dotenv", "session"]),
25
+ });
26
+ export const credentialErrorSchema = z.object({
27
+ id: z.string(),
28
+ key: z.string(),
29
+ error: z.string(),
30
+ code: z.enum(["NOT_FOUND", "ACCESS_DENIED", "INVALID_SESSION"]),
31
+ });
32
+ export const credentialResponseSchema = z.union([
33
+ credentialSuccessSchema,
34
+ credentialErrorSchema,
35
+ ]);
36
+ // ── Service Config ──────────────────────────────────────────────────────
37
+ export const credentialServiceConfigSchema = z.object({
38
+ /** Path to the SQLite database. Defaults to ~/.chapter/data/chapter.db. */
39
+ dbPath: z.string().optional(),
40
+ /** Path to the .env file for dotenv credential resolution. */
41
+ envFilePath: z.string().optional(),
42
+ /** macOS Keychain service name. */
43
+ keychainService: z.string().default("clawmasons"),
44
+ });
45
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,2EAA2E;AAE3E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,yEAAyE;IACzE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,0CAA0C;IAC1C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,mCAAmC;IACnC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,6BAA6B;IAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,8BAA8B;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,8EAA8E;IAC9E,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACxC,4CAA4C;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAIH,2EAA2E;AAE3E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;CACzD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;CAChE,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC;IAC9C,uBAAuB;IACvB,qBAAqB;CACtB,CAAC,CAAC;AAIH,2EAA2E;AAE3E,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,2EAA2E;IAC3E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,8DAA8D;IAC9D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,mCAAmC;IACnC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;CAClD,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type BetterSqlite3 from "better-sqlite3";
2
+ import type { CredentialRequest, CredentialResponse, CredentialServiceConfig } from "./schemas.js";
3
+ import { CredentialResolver } from "./resolver.js";
4
+ /**
5
+ * The credential service handles credential requests: validates access,
6
+ * resolves credentials, and logs audit entries.
7
+ *
8
+ * Can be used in SDK mode (in-process, no WebSocket) or behind the
9
+ * WebSocket client for production Docker deployments.
10
+ */
11
+ export declare class CredentialService {
12
+ private readonly resolver;
13
+ private readonly db;
14
+ constructor(config: CredentialServiceConfig, resolver?: CredentialResolver);
15
+ /**
16
+ * Handle a credential request: validate access → resolve → audit → respond.
17
+ */
18
+ handleRequest(request: CredentialRequest): Promise<CredentialResponse>;
19
+ /**
20
+ * Set session-scoped credential overrides.
21
+ *
22
+ * Session overrides take highest priority during credential resolution,
23
+ * checked before env, keychain, and dotenv sources. Used by the ACP proxy
24
+ * to inject credentials extracted from ACP client `mcpServers` env fields.
25
+ */
26
+ setSessionOverrides(overrides: Record<string, string>): void;
27
+ /**
28
+ * Clear all session-scoped credential overrides.
29
+ */
30
+ clearSessionOverrides(): void;
31
+ /**
32
+ * Close the database connection.
33
+ */
34
+ close(): void;
35
+ /**
36
+ * Get the underlying database (for testing/querying audit entries).
37
+ */
38
+ getDatabase(): BetterSqlite3.Database;
39
+ private audit;
40
+ }
41
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAMnD;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;gBAEhC,MAAM,EAAE,uBAAuB,EAAE,QAAQ,CAAC,EAAE,kBAAkB;IAQ1E;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuC5E;;;;;;OAMG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAI5D;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAI7B;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,WAAW,IAAI,aAAa,CAAC,QAAQ;IAIrC,OAAO,CAAC,KAAK;CAmBd"}
@@ -0,0 +1,99 @@
1
+ import { CredentialResolver } from "./resolver.js";
2
+ import { openCredentialDatabase, insertCredentialAudit, } from "./audit.js";
3
+ /**
4
+ * The credential service handles credential requests: validates access,
5
+ * resolves credentials, and logs audit entries.
6
+ *
7
+ * Can be used in SDK mode (in-process, no WebSocket) or behind the
8
+ * WebSocket client for production Docker deployments.
9
+ */
10
+ export class CredentialService {
11
+ resolver;
12
+ db;
13
+ constructor(config, resolver) {
14
+ this.resolver = resolver ?? new CredentialResolver({
15
+ envFilePath: config.envFilePath,
16
+ keychainService: config.keychainService,
17
+ });
18
+ this.db = openCredentialDatabase(config.dbPath);
19
+ }
20
+ /**
21
+ * Handle a credential request: validate access → resolve → audit → respond.
22
+ */
23
+ async handleRequest(request) {
24
+ const { id, key, agentId, declaredCredentials } = request;
25
+ // 1. Access validation — check key is in agent's declared credentials
26
+ if (!declaredCredentials.includes(key)) {
27
+ const reason = `Agent "${agentId}" has not declared credential "${key}"`;
28
+ this.audit(id, request, "denied", reason, null);
29
+ return {
30
+ id,
31
+ key,
32
+ error: reason,
33
+ code: "ACCESS_DENIED",
34
+ };
35
+ }
36
+ // 2. Resolve credential
37
+ const result = await this.resolver.resolve(key);
38
+ if ("error" in result) {
39
+ // Resolution failed — credential not found in any source
40
+ this.audit(id, request, "error", result.error, null);
41
+ return {
42
+ id,
43
+ key,
44
+ error: result.error,
45
+ code: "NOT_FOUND",
46
+ };
47
+ }
48
+ // 3. Success — return resolved value
49
+ this.audit(id, request, "granted", null, result.source);
50
+ return {
51
+ id,
52
+ key,
53
+ value: result.value,
54
+ source: result.source,
55
+ };
56
+ }
57
+ /**
58
+ * Set session-scoped credential overrides.
59
+ *
60
+ * Session overrides take highest priority during credential resolution,
61
+ * checked before env, keychain, and dotenv sources. Used by the ACP proxy
62
+ * to inject credentials extracted from ACP client `mcpServers` env fields.
63
+ */
64
+ setSessionOverrides(overrides) {
65
+ this.resolver.setSessionOverrides(overrides);
66
+ }
67
+ /**
68
+ * Clear all session-scoped credential overrides.
69
+ */
70
+ clearSessionOverrides() {
71
+ this.resolver.clearSessionOverrides();
72
+ }
73
+ /**
74
+ * Close the database connection.
75
+ */
76
+ close() {
77
+ this.db.close();
78
+ }
79
+ /**
80
+ * Get the underlying database (for testing/querying audit entries).
81
+ */
82
+ getDatabase() {
83
+ return this.db;
84
+ }
85
+ audit(id, request, outcome, denyReason, source) {
86
+ insertCredentialAudit(this.db, {
87
+ id,
88
+ timestamp: new Date().toISOString(),
89
+ agent_id: request.agentId,
90
+ role: request.role,
91
+ session_id: request.sessionId,
92
+ credential_key: request.key,
93
+ outcome,
94
+ deny_reason: denyReason,
95
+ source,
96
+ });
97
+ }
98
+ }
99
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { CredentialService } from "./service.js";
2
+ export interface CredentialWSClientOptions {
3
+ /** Maximum number of reconnect attempts. */
4
+ maxRetries?: number;
5
+ /** Delay between reconnect attempts in milliseconds. */
6
+ retryDelayMs?: number;
7
+ }
8
+ /**
9
+ * WebSocket client that connects to the proxy and handles credential
10
+ * requests relayed from agents.
11
+ */
12
+ export declare class CredentialWSClient {
13
+ private readonly service;
14
+ private readonly maxRetries;
15
+ private readonly retryDelayMs;
16
+ private ws;
17
+ private retryCount;
18
+ private proxyUrl;
19
+ private token;
20
+ private closed;
21
+ constructor(service: CredentialService, options?: CredentialWSClientOptions);
22
+ /**
23
+ * Connect to the proxy WebSocket endpoint.
24
+ *
25
+ * Resolves when the connection is established.
26
+ * Rejects if the connection fails after all retries.
27
+ */
28
+ connect(proxyUrl: string, token: string): Promise<void>;
29
+ /**
30
+ * Disconnect from the proxy.
31
+ */
32
+ disconnect(): void;
33
+ private attemptConnect;
34
+ private setupReconnectHandler;
35
+ private handleMessage;
36
+ private handleReconnect;
37
+ private delay;
38
+ }
39
+ //# sourceMappingURL=ws-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-client.d.ts","sourceRoot":"","sources":["../src/ws-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,yBAAyB;IACxC,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,iBAAiB,EAAE,OAAO,GAAE,yBAA8B;IAM/E;;;;;OAKG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB7D;;OAEG;IACH,UAAU,IAAI,IAAI;IAQlB,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,qBAAqB;YAUf,aAAa;YAuBb,eAAe;IA4B7B,OAAO,CAAC,KAAK;CAGd"}
@@ -0,0 +1,134 @@
1
+ import WebSocket from "ws";
2
+ import { credentialRequestSchema } from "./schemas.js";
3
+ /**
4
+ * WebSocket client that connects to the proxy and handles credential
5
+ * requests relayed from agents.
6
+ */
7
+ export class CredentialWSClient {
8
+ service;
9
+ maxRetries;
10
+ retryDelayMs;
11
+ ws = null;
12
+ retryCount = 0;
13
+ proxyUrl = "";
14
+ token = "";
15
+ closed = false;
16
+ constructor(service, options = {}) {
17
+ this.service = service;
18
+ this.maxRetries = options.maxRetries ?? 3;
19
+ this.retryDelayMs = options.retryDelayMs ?? 1000;
20
+ }
21
+ /**
22
+ * Connect to the proxy WebSocket endpoint.
23
+ *
24
+ * Resolves when the connection is established.
25
+ * Rejects if the connection fails after all retries.
26
+ */
27
+ async connect(proxyUrl, token) {
28
+ this.proxyUrl = proxyUrl;
29
+ this.token = token;
30
+ this.closed = false;
31
+ this.retryCount = 0;
32
+ while (!this.closed) {
33
+ try {
34
+ await this.attemptConnect();
35
+ return; // Connected successfully
36
+ }
37
+ catch {
38
+ this.retryCount++;
39
+ if (this.retryCount > this.maxRetries) {
40
+ throw new Error(`Max connection attempts (${this.maxRetries}) reached. Giving up.`);
41
+ }
42
+ console.log(`[credential-service] Reconnecting (attempt ${this.retryCount}/${this.maxRetries})...`);
43
+ await this.delay(this.retryDelayMs);
44
+ }
45
+ }
46
+ }
47
+ /**
48
+ * Disconnect from the proxy.
49
+ */
50
+ disconnect() {
51
+ this.closed = true;
52
+ if (this.ws) {
53
+ this.ws.close();
54
+ this.ws = null;
55
+ }
56
+ }
57
+ attemptConnect() {
58
+ return new Promise((resolve, reject) => {
59
+ const ws = new WebSocket(this.proxyUrl, {
60
+ headers: {
61
+ Authorization: `Bearer ${this.token}`,
62
+ },
63
+ });
64
+ ws.on("open", () => {
65
+ this.ws = ws;
66
+ this.retryCount = 0;
67
+ this.setupReconnectHandler(ws);
68
+ resolve();
69
+ });
70
+ ws.on("message", (data) => {
71
+ this.handleMessage(data).catch((err) => {
72
+ console.error("[credential-service] Error handling message:", err);
73
+ });
74
+ });
75
+ ws.on("error", (err) => {
76
+ reject(err);
77
+ });
78
+ });
79
+ }
80
+ setupReconnectHandler(ws) {
81
+ ws.on("close", () => {
82
+ if (!this.closed) {
83
+ this.handleReconnect().catch((err) => {
84
+ console.error("[credential-service] Reconnect failed:", err);
85
+ });
86
+ }
87
+ });
88
+ }
89
+ async handleMessage(data) {
90
+ const raw = data.toString("utf-8");
91
+ let parsed;
92
+ try {
93
+ parsed = JSON.parse(raw);
94
+ }
95
+ catch {
96
+ console.error("[credential-service] Invalid JSON received:", raw);
97
+ return;
98
+ }
99
+ const result = credentialRequestSchema.safeParse(parsed);
100
+ if (!result.success) {
101
+ console.error("[credential-service] Invalid request:", result.error.message);
102
+ return;
103
+ }
104
+ const response = await this.service.handleRequest(result.data);
105
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
106
+ this.ws.send(JSON.stringify(response));
107
+ }
108
+ }
109
+ async handleReconnect() {
110
+ if (this.closed)
111
+ return;
112
+ this.retryCount = 0;
113
+ while (!this.closed) {
114
+ this.retryCount++;
115
+ if (this.retryCount > this.maxRetries) {
116
+ console.error(`[credential-service] Max reconnect attempts (${this.maxRetries}) reached. Giving up.`);
117
+ return;
118
+ }
119
+ console.log(`[credential-service] Reconnecting (attempt ${this.retryCount}/${this.maxRetries})...`);
120
+ await this.delay(this.retryDelayMs);
121
+ try {
122
+ await this.attemptConnect();
123
+ return; // Reconnected successfully
124
+ }
125
+ catch {
126
+ // Will retry in next iteration
127
+ }
128
+ }
129
+ }
130
+ delay(ms) {
131
+ return new Promise((resolve) => setTimeout(resolve, ms));
132
+ }
133
+ }
134
+ //# sourceMappingURL=ws-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-client.js","sourceRoot":"","sources":["../src/ws-client.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@clawmasons/credential-service",
3
+ "version": "0.1.0",
4
+ "description": "Credential resolution and distribution service for Clawmasons Chapter",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "bin": {
15
+ "credential-service": "./dist/cli.js"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.build.json",
19
+ "typecheck": "tsc --noEmit"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "better-sqlite3": "^12.6.2",
27
+ "ws": "^8.19.0",
28
+ "zod": "^3.24.0"
29
+ }
30
+ }