@guardion/guardion 0.2.0 → 0.3.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/config.yaml.example +72 -14
- package/dist/cli.js +112 -103
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +119 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +72 -25
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +8 -3
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +18 -8
- package/dist/constants.js.map +1 -1
- package/dist/installer.d.ts +2 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +84 -31
- package/dist/installer.js.map +1 -1
- package/dist/keychain.d.ts.map +1 -1
- package/dist/keychain.js +53 -15
- package/dist/keychain.js.map +1 -1
- package/dist/mock-server.d.ts.map +1 -1
- package/dist/mock-server.js +19 -4
- package/dist/mock-server.js.map +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js.map +1 -1
- package/hooks/guardion-hook.cjs +105 -74
- package/package.json +1 -1
package/dist/keychain.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
-
import { KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, TOKEN_FILE_PATH, SYSTEM_TOKEN_PATH } from './constants.js';
|
|
3
|
+
import { KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, TOKEN_FILE_PATH, SYSTEM_TOKEN_PATH, } from './constants.js';
|
|
4
4
|
const KEYCHAIN_TIMEOUT = 2000;
|
|
5
5
|
// ── Get ───────────────────────────────────────────────────────────────────────
|
|
6
6
|
export function getToken() {
|
|
@@ -25,14 +25,18 @@ export function getToken() {
|
|
|
25
25
|
if (t)
|
|
26
26
|
return t;
|
|
27
27
|
}
|
|
28
|
-
catch {
|
|
28
|
+
catch {
|
|
29
|
+
/* absent */
|
|
30
|
+
}
|
|
29
31
|
// 5. User file fallback
|
|
30
32
|
try {
|
|
31
33
|
const t = fs.readFileSync(TOKEN_FILE_PATH, 'utf-8').trim();
|
|
32
34
|
if (t)
|
|
33
35
|
return t;
|
|
34
36
|
}
|
|
35
|
-
catch {
|
|
37
|
+
catch {
|
|
38
|
+
/* absent */
|
|
39
|
+
}
|
|
36
40
|
return '';
|
|
37
41
|
}
|
|
38
42
|
// ── Set ───────────────────────────────────────────────────────────────────────
|
|
@@ -51,7 +55,10 @@ export function setToken(token) {
|
|
|
51
55
|
import('node:path').then(({ default: p }) => {
|
|
52
56
|
const dir = p.join(o.homedir(), '.guardion');
|
|
53
57
|
f.mkdirSync(dir, { recursive: true });
|
|
54
|
-
f.writeFileSync(TOKEN_FILE_PATH, token, {
|
|
58
|
+
f.writeFileSync(TOKEN_FILE_PATH, token, {
|
|
59
|
+
encoding: 'utf-8',
|
|
60
|
+
mode: 0o600,
|
|
61
|
+
});
|
|
55
62
|
});
|
|
56
63
|
});
|
|
57
64
|
});
|
|
@@ -60,21 +67,40 @@ export function clearToken() {
|
|
|
60
67
|
if (process.platform === 'darwin') {
|
|
61
68
|
try {
|
|
62
69
|
execFileSync('security', [
|
|
63
|
-
'delete-generic-password',
|
|
70
|
+
'delete-generic-password',
|
|
71
|
+
'-s',
|
|
72
|
+
KEYCHAIN_SERVICE,
|
|
73
|
+
'-a',
|
|
74
|
+
KEYCHAIN_ACCOUNT,
|
|
64
75
|
], { timeout: KEYCHAIN_TIMEOUT, stdio: 'pipe' });
|
|
65
76
|
}
|
|
66
|
-
catch {
|
|
77
|
+
catch {
|
|
78
|
+
/* not found */
|
|
79
|
+
}
|
|
67
80
|
return;
|
|
68
81
|
}
|
|
69
82
|
try {
|
|
70
83
|
fs.unlinkSync(TOKEN_FILE_PATH);
|
|
71
84
|
}
|
|
72
|
-
catch {
|
|
85
|
+
catch {
|
|
86
|
+
/* absent */
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
89
|
// ── macOS Keychain ────────────────────────────────────────────────────────────
|
|
75
90
|
function keychainGet() {
|
|
76
91
|
try {
|
|
77
|
-
return execFileSync('security', [
|
|
92
|
+
return execFileSync('security', [
|
|
93
|
+
'find-generic-password',
|
|
94
|
+
'-s',
|
|
95
|
+
KEYCHAIN_SERVICE,
|
|
96
|
+
'-a',
|
|
97
|
+
KEYCHAIN_ACCOUNT,
|
|
98
|
+
'-w',
|
|
99
|
+
], {
|
|
100
|
+
timeout: KEYCHAIN_TIMEOUT,
|
|
101
|
+
encoding: 'utf8',
|
|
102
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
103
|
+
}).trim();
|
|
78
104
|
}
|
|
79
105
|
catch {
|
|
80
106
|
return '';
|
|
@@ -84,22 +110,33 @@ function keychainSet(token) {
|
|
|
84
110
|
// Delete existing entry first (add fails if it already exists)
|
|
85
111
|
try {
|
|
86
112
|
execFileSync('security', [
|
|
87
|
-
'delete-generic-password',
|
|
113
|
+
'delete-generic-password',
|
|
114
|
+
'-s',
|
|
115
|
+
KEYCHAIN_SERVICE,
|
|
116
|
+
'-a',
|
|
117
|
+
KEYCHAIN_ACCOUNT,
|
|
88
118
|
], { timeout: KEYCHAIN_TIMEOUT, stdio: 'pipe' });
|
|
89
119
|
}
|
|
90
|
-
catch {
|
|
120
|
+
catch {
|
|
121
|
+
/* not found — ok */
|
|
122
|
+
}
|
|
91
123
|
execFileSync('security', [
|
|
92
124
|
'add-generic-password',
|
|
93
|
-
'-s',
|
|
94
|
-
|
|
95
|
-
'-
|
|
125
|
+
'-s',
|
|
126
|
+
KEYCHAIN_SERVICE,
|
|
127
|
+
'-a',
|
|
128
|
+
KEYCHAIN_ACCOUNT,
|
|
129
|
+
'-w',
|
|
130
|
+
token,
|
|
96
131
|
], { timeout: KEYCHAIN_TIMEOUT, stdio: 'pipe' });
|
|
97
132
|
}
|
|
98
133
|
// ── Windows Credential Manager ────────────────────────────────────────────────
|
|
99
134
|
function windowsCredGet() {
|
|
100
135
|
try {
|
|
101
136
|
const out = execFileSync('cmdkey', ['/list:guardion'], {
|
|
102
|
-
timeout: KEYCHAIN_TIMEOUT,
|
|
137
|
+
timeout: KEYCHAIN_TIMEOUT,
|
|
138
|
+
encoding: 'utf8',
|
|
139
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
103
140
|
});
|
|
104
141
|
// Parse token from output (stored in generic credential)
|
|
105
142
|
const match = out.match(/Password:\s*(.+)/);
|
|
@@ -111,7 +148,8 @@ function windowsCredGet() {
|
|
|
111
148
|
}
|
|
112
149
|
function windowsCredSet(token) {
|
|
113
150
|
execFileSync('cmdkey', [`/add:guardion`, `/user:token`, `/pass:${token}`], {
|
|
114
|
-
timeout: KEYCHAIN_TIMEOUT,
|
|
151
|
+
timeout: KEYCHAIN_TIMEOUT,
|
|
152
|
+
stdio: 'pipe',
|
|
115
153
|
});
|
|
116
154
|
}
|
|
117
155
|
//# sourceMappingURL=keychain.js.map
|
package/dist/keychain.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../src/keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../src/keychain.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-server.d.ts","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mock-server.d.ts","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"AAgDA,wBAAgB,eAAe,CAAC,IAAI,SAAe,QAiHlD"}
|
package/dist/mock-server.js
CHANGED
|
@@ -5,9 +5,20 @@ const EVENTS_PATH = '/v1/hooks/events'; // matches real Guard API — fixed from
|
|
|
5
5
|
const HEALTH_PATH = '/health';
|
|
6
6
|
let nextId = 1;
|
|
7
7
|
const logs = [];
|
|
8
|
-
function ts() {
|
|
8
|
+
function ts() {
|
|
9
|
+
return new Date().toISOString().slice(11, 23);
|
|
10
|
+
}
|
|
9
11
|
function addLog(method, p, status, duration_ms, body, meta = {}) {
|
|
10
|
-
const entry = {
|
|
12
|
+
const entry = {
|
|
13
|
+
id: nextId++,
|
|
14
|
+
timestamp: new Date().toISOString(),
|
|
15
|
+
method,
|
|
16
|
+
path: p,
|
|
17
|
+
status,
|
|
18
|
+
duration_ms,
|
|
19
|
+
body,
|
|
20
|
+
meta,
|
|
21
|
+
};
|
|
11
22
|
logs.push(entry);
|
|
12
23
|
if (logs.length > 2000)
|
|
13
24
|
logs.splice(0, logs.length - 2000);
|
|
@@ -42,7 +53,9 @@ export function startMockServer(port = DEFAULT_PORT) {
|
|
|
42
53
|
console.log(chalk.red(` ✗ ${body.error_type}: ${String(body.error_message).slice(0, 120)}`));
|
|
43
54
|
if (body.metadata && typeof body.metadata === 'object') {
|
|
44
55
|
const m = body.metadata;
|
|
45
|
-
const who = [m.os_user, m.hostname, m.git_user_email]
|
|
56
|
+
const who = [m.os_user, m.hostname, m.git_user_email]
|
|
57
|
+
.filter(Boolean)
|
|
58
|
+
.join(' @ ');
|
|
46
59
|
if (who)
|
|
47
60
|
console.log(chalk.cyan(` user: ${who}`));
|
|
48
61
|
if (m.git_branch)
|
|
@@ -73,7 +86,9 @@ export function startMockServer(port = DEFAULT_PORT) {
|
|
|
73
86
|
});
|
|
74
87
|
app.get('/api/logs', (req, res) => {
|
|
75
88
|
const event = req.query.event;
|
|
76
|
-
const filtered = event
|
|
89
|
+
const filtered = event
|
|
90
|
+
? logs.filter((l) => l.meta.hook_event_name === event)
|
|
91
|
+
: logs;
|
|
77
92
|
res.json({ count: filtered.length, logs: filtered.slice(-200) });
|
|
78
93
|
});
|
|
79
94
|
// ── Dashboard ──────────────────────────────────────────────────────────────
|
package/dist/mock-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-server.js","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mock-server.js","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"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"}
|
package/dist/scanner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC7C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAMpE;AAED,wBAAgB,IAAI,IAAI,UAAU,CAejC"}
|
package/dist/scanner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAGzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AA0BtD,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAmB,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,MAAM,YAAY,GAAG,oBAAoB,CAAC;IAC1C,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG;QACjB,GAAG,CAAC,QAAQ,EAAE,UAAU,IAAI,EAAE,CAAC;KAChC,CAAC;IAEF,uEAAuE;IACvE,MAAM,mBAAmB,GAAG,OAAO,CACjC,QAAQ,EAAE,GAAG,EAAE,aAAa;QAC1B,QAAQ,EAAE,GAAG,EAAE,gBAAgB;QAC/B,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC7D,CAAC;IAEF,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC;AACrE,CAAC"}
|
package/hooks/guardion-hook.cjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Guardion Claude Code hook —
|
|
3
|
+
* Guardion Claude Code hook — tier-aware event forwarder.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Tiers:
|
|
6
|
+
* hooks — fire-and-forget POST to Guard API, no LLM proxy involvement
|
|
7
|
+
* full — same + on SessionStart injects x-guardion-trace-id into
|
|
8
|
+
* ANTHROPIC_CUSTOM_HEADERS so every LLM call through the
|
|
9
|
+
* Guardion gateway is correlated to this session
|
|
10
|
+
*
|
|
11
|
+
* Config (~/.guardion/config.json, written by `npx guardion init`):
|
|
12
|
+
* tier, api_url, policy, application, gateway.*, hooks.events, hooks.timeout_ms
|
|
7
13
|
*
|
|
8
|
-
*
|
|
9
|
-
* ~/.guardion/
|
|
10
|
-
* GUARDION_API_URL env override for CI / testing
|
|
11
|
-
* GUARDION_POLICY env override for CI / testing
|
|
14
|
+
* Token resolution (first match wins):
|
|
15
|
+
* GUARDION_TOKEN env → macOS Keychain → /etc/guardion/token → ~/.guardion/token
|
|
12
16
|
*
|
|
13
|
-
*
|
|
14
|
-
* GUARDION_TOKEN env CI / testing
|
|
15
|
-
* macOS Keychain service=guardion, account=token
|
|
16
|
-
* /etc/guardion/token enterprise MDM, root-owned
|
|
17
|
-
* ~/.guardion/token user-level fallback
|
|
17
|
+
* Always exits 0 — never blocks Claude Code.
|
|
18
18
|
*/
|
|
19
19
|
'use strict';
|
|
20
20
|
|
|
@@ -25,27 +25,26 @@ const http = require('http');
|
|
|
25
25
|
const https = require('https');
|
|
26
26
|
const { execFileSync } = require('child_process');
|
|
27
27
|
|
|
28
|
-
// ──
|
|
28
|
+
// ── Paths ────────────────────────────────────────────────────────────────────
|
|
29
29
|
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const SESSION_DIR
|
|
35
|
-
const
|
|
36
|
-
const HOOK_EVENTS_PATH = '/v1/hooks/events';
|
|
30
|
+
const HOME_DIR = os.homedir();
|
|
31
|
+
const GUARDION_DIR = path.join(HOME_DIR, '.guardion');
|
|
32
|
+
const CONFIG_JSON = path.join(GUARDION_DIR, 'config.json');
|
|
33
|
+
const CURRENT_SESSION = path.join(GUARDION_DIR, 'current-session');
|
|
34
|
+
const SESSION_DIR = path.join(GUARDION_DIR, 'sessions');
|
|
35
|
+
const SETTINGS_PATH = path.join(HOME_DIR, '.claude', 'settings.json');
|
|
37
36
|
|
|
38
37
|
// ── Config ───────────────────────────────────────────────────────────────────
|
|
39
38
|
|
|
40
39
|
function loadConfig() {
|
|
41
40
|
try {
|
|
42
|
-
return JSON.parse(fs.readFileSync(
|
|
41
|
+
return JSON.parse(fs.readFileSync(CONFIG_JSON, 'utf8'));
|
|
43
42
|
} catch {
|
|
44
43
|
return {
|
|
44
|
+
tier: process.env.GUARDION_TIER || 'hooks',
|
|
45
45
|
api_url: process.env.GUARDION_API_URL || 'https://api.guardion.ai',
|
|
46
46
|
policy: process.env.GUARDION_POLICY || '',
|
|
47
47
|
application: process.env.GUARDION_APPLICATION || 'claude-code',
|
|
48
|
-
tier: process.env.GUARDION_TIER || 'hooks',
|
|
49
48
|
};
|
|
50
49
|
}
|
|
51
50
|
}
|
|
@@ -54,35 +53,31 @@ function loadConfig() {
|
|
|
54
53
|
|
|
55
54
|
function resolveToken() {
|
|
56
55
|
if (process.env.GUARDION_TOKEN) return process.env.GUARDION_TOKEN.trim();
|
|
57
|
-
|
|
58
56
|
if (process.platform === 'darwin') {
|
|
59
57
|
try {
|
|
60
|
-
const t = execFileSync(
|
|
61
|
-
'security',
|
|
58
|
+
const t = execFileSync('security',
|
|
62
59
|
['find-generic-password', '-s', 'guardion', '-a', 'token', '-w'],
|
|
63
|
-
{ timeout:
|
|
60
|
+
{ timeout: 1000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
|
|
64
61
|
).trim();
|
|
65
62
|
if (t) return t;
|
|
66
|
-
} catch { /* not
|
|
63
|
+
} catch { /* not found */ }
|
|
67
64
|
}
|
|
68
|
-
|
|
69
65
|
for (const p of ['/etc/guardion/token', path.join(GUARDION_DIR, 'token')]) {
|
|
70
66
|
try {
|
|
71
67
|
const t = fs.readFileSync(p, 'utf8').trim();
|
|
72
68
|
if (t) return t;
|
|
73
|
-
} catch { /*
|
|
69
|
+
} catch { /* absent */ }
|
|
74
70
|
}
|
|
75
|
-
|
|
76
71
|
return '';
|
|
77
72
|
}
|
|
78
73
|
|
|
79
|
-
// ── Session
|
|
74
|
+
// ── Session files ────────────────────────────────────────────────────────────
|
|
80
75
|
|
|
81
|
-
function writeCurrentSession(
|
|
76
|
+
function writeCurrentSession(id) {
|
|
82
77
|
try {
|
|
83
78
|
fs.mkdirSync(GUARDION_DIR, { recursive: true });
|
|
84
79
|
const tmp = CURRENT_SESSION + '.tmp';
|
|
85
|
-
fs.writeFileSync(tmp,
|
|
80
|
+
fs.writeFileSync(tmp, id, 'utf8');
|
|
86
81
|
fs.renameSync(tmp, CURRENT_SESSION);
|
|
87
82
|
} catch { /* non-critical */ }
|
|
88
83
|
}
|
|
@@ -92,51 +87,77 @@ function readCurrentSession() {
|
|
|
92
87
|
}
|
|
93
88
|
|
|
94
89
|
function deleteCurrentSession() {
|
|
95
|
-
try { fs.unlinkSync(CURRENT_SESSION); } catch { /*
|
|
90
|
+
try { fs.unlinkSync(CURRENT_SESSION); } catch { /* gone */ }
|
|
96
91
|
}
|
|
97
92
|
|
|
98
|
-
function writeSessionMeta(
|
|
93
|
+
function writeSessionMeta(id, meta) {
|
|
99
94
|
try {
|
|
100
95
|
fs.mkdirSync(SESSION_DIR, { recursive: true });
|
|
101
|
-
fs.writeFileSync(
|
|
102
|
-
path.join(SESSION_DIR, `${sessionId}.json`),
|
|
103
|
-
JSON.stringify(meta, null, 2),
|
|
104
|
-
'utf8'
|
|
105
|
-
);
|
|
96
|
+
fs.writeFileSync(path.join(SESSION_DIR, `${id}.json`), JSON.stringify(meta, null, 2), 'utf8');
|
|
106
97
|
} catch { /* non-critical */ }
|
|
107
98
|
}
|
|
108
99
|
|
|
109
|
-
function deleteSessionMeta(
|
|
110
|
-
if (!
|
|
111
|
-
try { fs.unlinkSync(path.join(SESSION_DIR, `${
|
|
100
|
+
function deleteSessionMeta(id) {
|
|
101
|
+
if (!id) return;
|
|
102
|
+
try { fs.unlinkSync(path.join(SESSION_DIR, `${id}.json`)); } catch { /* gone */ }
|
|
112
103
|
}
|
|
113
104
|
|
|
114
|
-
// ──
|
|
105
|
+
// ── Full-tier: settings.json rewrite ─────────────────────────────────────────
|
|
106
|
+
// Injects x-guardion-trace-id (and optionally x-guardion-metadata) into
|
|
107
|
+
// ANTHROPIC_CUSTOM_HEADERS so the gateway correlates LLM calls to this session.
|
|
108
|
+
// Written atomically (tmp → rename) to avoid partial-write corruption.
|
|
115
109
|
|
|
116
|
-
function
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
110
|
+
function injectTraceHeaders(sessionId, metadata) {
|
|
111
|
+
try {
|
|
112
|
+
const raw = fs.readFileSync(SETTINGS_PATH, 'utf8');
|
|
113
|
+
const settings = JSON.parse(raw);
|
|
114
|
+
settings.env = settings.env || {};
|
|
115
|
+
|
|
116
|
+
const existing = (settings.env.ANTHROPIC_CUSTOM_HEADERS || '').split('\n');
|
|
117
|
+
const filtered = existing.filter(l =>
|
|
118
|
+
!l.startsWith('x-guardion-trace-id:') &&
|
|
119
|
+
!l.startsWith('x-guardion-metadata:')
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
filtered.push(`x-guardion-trace-id: ${sessionId}`);
|
|
123
|
+
if (metadata) {
|
|
124
|
+
const b64 = Buffer.from(JSON.stringify(metadata)).toString('base64');
|
|
125
|
+
filtered.push(`x-guardion-metadata: ${b64}`);
|
|
121
126
|
}
|
|
127
|
+
|
|
128
|
+
settings.env.ANTHROPIC_CUSTOM_HEADERS = filtered.join('\n');
|
|
129
|
+
settings.env.GUARDION_TRACE_ID = sessionId;
|
|
130
|
+
|
|
131
|
+
const tmp = SETTINGS_PATH + '.tmp';
|
|
132
|
+
fs.writeFileSync(tmp, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
133
|
+
fs.renameSync(tmp, SETTINGS_PATH);
|
|
134
|
+
} catch (e) {
|
|
135
|
+
process.stderr.write(`[guardion] settings rewrite error: ${e.message}\n`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ── HTTP POST ────────────────────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
function postEvent(apiUrl, token, payload, timeoutMs) {
|
|
142
|
+
return new Promise(resolve => {
|
|
143
|
+
let url;
|
|
144
|
+
try { url = new URL('/v1/hooks/events', apiUrl); } catch { return resolve(); }
|
|
145
|
+
|
|
122
146
|
const transport = url.protocol === 'https:' ? https : http;
|
|
123
|
-
const body
|
|
124
|
-
|
|
125
|
-
const req = transport.request(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
'Content-Length': Buffer.byteLength(body),
|
|
135
|
-
},
|
|
136
|
-
timeout: HOOK_TIMEOUT_MS,
|
|
147
|
+
const body = JSON.stringify(payload);
|
|
148
|
+
|
|
149
|
+
const req = transport.request({
|
|
150
|
+
hostname: url.hostname,
|
|
151
|
+
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
152
|
+
path: url.pathname,
|
|
153
|
+
method: 'POST',
|
|
154
|
+
headers: {
|
|
155
|
+
'Content-Type': 'application/json',
|
|
156
|
+
'Authorization': `Bearer ${token}`,
|
|
157
|
+
'Content-Length': Buffer.byteLength(body),
|
|
137
158
|
},
|
|
138
|
-
|
|
139
|
-
);
|
|
159
|
+
timeout: timeoutMs,
|
|
160
|
+
}, res => { res.resume(); res.on('end', resolve); });
|
|
140
161
|
|
|
141
162
|
req.on('error', resolve);
|
|
142
163
|
req.on('timeout', () => { req.destroy(); resolve(); });
|
|
@@ -145,7 +166,7 @@ function postEvent(apiUrl, token, payload) {
|
|
|
145
166
|
});
|
|
146
167
|
}
|
|
147
168
|
|
|
148
|
-
// ── Metadata
|
|
169
|
+
// ── Metadata ─────────────────────────────────────────────────────────────────
|
|
149
170
|
|
|
150
171
|
function collectMetadata(payload) {
|
|
151
172
|
try {
|
|
@@ -156,25 +177,27 @@ function collectMetadata(payload) {
|
|
|
156
177
|
}
|
|
157
178
|
}
|
|
158
179
|
|
|
159
|
-
// ── Main
|
|
180
|
+
// ── Main ─────────────────────────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
const config = loadConfig();
|
|
183
|
+
const timeoutMs = (config.hooks && config.hooks.timeout_ms) || 3000;
|
|
160
184
|
|
|
161
|
-
//
|
|
162
|
-
setTimeout(() => process.exit(0),
|
|
185
|
+
// Hard exit — never hang Claude Code
|
|
186
|
+
setTimeout(() => process.exit(0), timeoutMs + 1500);
|
|
163
187
|
|
|
164
188
|
let rawInput = '';
|
|
165
189
|
process.stdin.setEncoding('utf8');
|
|
166
|
-
process.stdin.on('data',
|
|
190
|
+
process.stdin.on('data', chunk => { rawInput += chunk; });
|
|
167
191
|
process.stdin.on('end', async () => {
|
|
168
192
|
let payload;
|
|
169
193
|
try { payload = JSON.parse(rawInput); } catch { return process.exit(0); }
|
|
170
194
|
|
|
171
|
-
const
|
|
172
|
-
const token = resolveToken();
|
|
195
|
+
const token = resolveToken();
|
|
173
196
|
if (!token) return process.exit(0);
|
|
174
197
|
|
|
175
198
|
const event = payload.hook_event_name || payload.event || '';
|
|
176
199
|
|
|
177
|
-
//
|
|
200
|
+
// Attach policy + application to every event
|
|
178
201
|
if (config.policy) payload.policy = config.policy;
|
|
179
202
|
if (config.application) payload.application = config.application;
|
|
180
203
|
|
|
@@ -187,16 +210,24 @@ process.stdin.on('end', async () => {
|
|
|
187
210
|
|
|
188
211
|
writeCurrentSession(sessionId);
|
|
189
212
|
writeSessionMeta(sessionId, meta);
|
|
213
|
+
|
|
214
|
+
// Full tier: inject trace-id into ANTHROPIC_CUSTOM_HEADERS so the gateway
|
|
215
|
+
// can correlate every subsequent LLM call to this session
|
|
216
|
+
if (config.tier === 'full') {
|
|
217
|
+
injectTraceHeaders(sessionId, meta);
|
|
218
|
+
}
|
|
219
|
+
|
|
190
220
|
} else if (event === 'SessionEnd') {
|
|
191
221
|
const sessionId = payload.session_id || readCurrentSession();
|
|
192
222
|
payload.trace_id = sessionId;
|
|
193
223
|
deleteCurrentSession();
|
|
194
224
|
deleteSessionMeta(sessionId);
|
|
225
|
+
|
|
195
226
|
} else {
|
|
196
227
|
const traceId = process.env.GUARDION_TRACE_ID || readCurrentSession();
|
|
197
228
|
if (traceId) payload.trace_id = traceId;
|
|
198
229
|
}
|
|
199
230
|
|
|
200
|
-
await postEvent(config.api_url, token, payload);
|
|
231
|
+
await postEvent(config.api_url, token, payload, timeoutMs);
|
|
201
232
|
process.exit(0);
|
|
202
233
|
});
|