@solongate/proxy 0.82.91 → 0.82.92
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/dist/index.js +12 -6
- package/dist/tui/index.js +12 -6
- package/dist/tui/local-log.d.ts +2 -0
- package/hooks/guard.bundled.mjs +11 -1
- package/hooks/guard.mjs +19 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7446,20 +7446,15 @@ function ensureLocalLogOwner(activeApiKey) {
|
|
|
7446
7446
|
} catch {
|
|
7447
7447
|
}
|
|
7448
7448
|
if (have === want) return false;
|
|
7449
|
-
const cleared = localLogExists();
|
|
7450
|
-
if (cleared) clearLocalLog();
|
|
7451
7449
|
try {
|
|
7452
7450
|
writeFileSync6(marker, want);
|
|
7453
7451
|
} catch {
|
|
7454
7452
|
}
|
|
7455
|
-
return
|
|
7453
|
+
return false;
|
|
7456
7454
|
} catch {
|
|
7457
7455
|
return false;
|
|
7458
7456
|
}
|
|
7459
7457
|
}
|
|
7460
|
-
function localLogExists() {
|
|
7461
|
-
return existsSync4(localLogFile());
|
|
7462
|
-
}
|
|
7463
7458
|
function tailLines(file, maxBytes = 131072) {
|
|
7464
7459
|
try {
|
|
7465
7460
|
const size = statSync(file).size;
|
|
@@ -7519,11 +7514,22 @@ function reasonSignals(reason) {
|
|
|
7519
7514
|
}
|
|
7520
7515
|
return { dlp, burst: RL_REASON.test(r) };
|
|
7521
7516
|
}
|
|
7517
|
+
function ownMark() {
|
|
7518
|
+
try {
|
|
7519
|
+
const p = join8(homedir6(), ".solongate", "cloud-guard.json");
|
|
7520
|
+
const c2 = JSON.parse(readFileSync8(p, "utf-8"));
|
|
7521
|
+
return c2?.apiKey ? createHash2("sha256").update(c2.apiKey).digest("hex").slice(0, 16) : "";
|
|
7522
|
+
} catch {
|
|
7523
|
+
return "";
|
|
7524
|
+
}
|
|
7525
|
+
}
|
|
7522
7526
|
function parseLocalLines(lines) {
|
|
7523
7527
|
const out2 = [];
|
|
7528
|
+
const mine = ownMark();
|
|
7524
7529
|
for (const line of lines) {
|
|
7525
7530
|
try {
|
|
7526
7531
|
const j = JSON.parse(line);
|
|
7532
|
+
if (mine && j.acct !== mine) continue;
|
|
7527
7533
|
const at = Date.parse(j.ts ?? "");
|
|
7528
7534
|
if (Number.isFinite(at)) out2.push({ ...j, at });
|
|
7529
7535
|
} catch {
|
package/dist/tui/index.js
CHANGED
|
@@ -782,20 +782,15 @@ function ensureLocalLogOwner(activeApiKey) {
|
|
|
782
782
|
} catch {
|
|
783
783
|
}
|
|
784
784
|
if (have === want) return false;
|
|
785
|
-
const cleared = localLogExists();
|
|
786
|
-
if (cleared) clearLocalLog();
|
|
787
785
|
try {
|
|
788
786
|
writeFileSync(marker, want);
|
|
789
787
|
} catch {
|
|
790
788
|
}
|
|
791
|
-
return
|
|
789
|
+
return false;
|
|
792
790
|
} catch {
|
|
793
791
|
return false;
|
|
794
792
|
}
|
|
795
793
|
}
|
|
796
|
-
function localLogExists() {
|
|
797
|
-
return existsSync(localLogFile());
|
|
798
|
-
}
|
|
799
794
|
function tailLines(file, maxBytes = 131072) {
|
|
800
795
|
try {
|
|
801
796
|
const size = statSync(file).size;
|
|
@@ -857,11 +852,22 @@ function reasonSignals(reason) {
|
|
|
857
852
|
}
|
|
858
853
|
return { dlp, burst: RL_REASON.test(r) };
|
|
859
854
|
}
|
|
855
|
+
function ownMark() {
|
|
856
|
+
try {
|
|
857
|
+
const p = join2(homedir2(), ".solongate", "cloud-guard.json");
|
|
858
|
+
const c2 = JSON.parse(readFileSync2(p, "utf-8"));
|
|
859
|
+
return c2?.apiKey ? createHash("sha256").update(c2.apiKey).digest("hex").slice(0, 16) : "";
|
|
860
|
+
} catch {
|
|
861
|
+
return "";
|
|
862
|
+
}
|
|
863
|
+
}
|
|
860
864
|
function parseLocalLines(lines) {
|
|
861
865
|
const out = [];
|
|
866
|
+
const mine = ownMark();
|
|
862
867
|
for (const line of lines) {
|
|
863
868
|
try {
|
|
864
869
|
const j = JSON.parse(line);
|
|
870
|
+
if (mine && j.acct !== mine) continue;
|
|
865
871
|
const at = Date.parse(j.ts ?? "");
|
|
866
872
|
if (Number.isFinite(at)) out.push({ ...j, at });
|
|
867
873
|
} catch {
|
package/dist/tui/local-log.d.ts
CHANGED
|
@@ -49,6 +49,8 @@ export interface LocalLogLine {
|
|
|
49
49
|
permission?: string;
|
|
50
50
|
trust_level?: string;
|
|
51
51
|
session_id?: string;
|
|
52
|
+
/** Hash prefix of the account that wrote this line. */
|
|
53
|
+
acct?: string;
|
|
52
54
|
agent_name?: string;
|
|
53
55
|
evaluation_time_ms?: number;
|
|
54
56
|
matched_rule_id?: string;
|
package/hooks/guard.bundled.mjs
CHANGED
|
@@ -6536,7 +6536,7 @@ import { resolve, join, dirname, isAbsolute } from "node:path";
|
|
|
6536
6536
|
import { homedir } from "node:os";
|
|
6537
6537
|
import { gunzipSync } from "node:zlib";
|
|
6538
6538
|
import { createHash } from "node:crypto";
|
|
6539
|
-
var HOOK_VERSION =
|
|
6539
|
+
var HOOK_VERSION = 67;
|
|
6540
6540
|
function localLogsOnly(security) {
|
|
6541
6541
|
if (security && typeof security === "object") {
|
|
6542
6542
|
const l = security.localLogs;
|
|
@@ -6557,8 +6557,18 @@ function writeLocalMarker(security) {
|
|
|
6557
6557
|
} catch {
|
|
6558
6558
|
}
|
|
6559
6559
|
}
|
|
6560
|
+
function accountMark() {
|
|
6561
|
+
try {
|
|
6562
|
+
return API_KEY ? createHash("sha256").update(API_KEY).digest("hex").slice(0, 16) : "";
|
|
6563
|
+
} catch {
|
|
6564
|
+
return "";
|
|
6565
|
+
}
|
|
6566
|
+
}
|
|
6560
6567
|
function writeLocalLog(security, entry) {
|
|
6561
6568
|
try {
|
|
6569
|
+
const mark = accountMark();
|
|
6570
|
+
if (mark)
|
|
6571
|
+
entry = { ...entry, acct: mark };
|
|
6562
6572
|
const l = security && security.localLogs;
|
|
6563
6573
|
if (!l || !l.enabled || typeof l.path !== "string" || !l.path.trim()) {
|
|
6564
6574
|
if (!localLogsOnly(security))
|
package/hooks/guard.mjs
CHANGED
|
@@ -32,7 +32,7 @@ import { createHash } from 'node:crypto';
|
|
|
32
32
|
// the installed hook self-updates when the cloud version is higher (see
|
|
33
33
|
// maybeSelfUpdate). This is what makes guard fixes propagate without a manual
|
|
34
34
|
// reinstall — the same trust model as the OPA WASM this hook already runs.
|
|
35
|
-
const HOOK_VERSION =
|
|
35
|
+
const HOOK_VERSION = 67;
|
|
36
36
|
|
|
37
37
|
// True when local log storage is ON. In that mode logs are kept LOCAL ONLY and
|
|
38
38
|
// nothing is sent to the cloud audit log.
|
|
@@ -96,8 +96,26 @@ function resolveLocalLogDir(rawPath) {
|
|
|
96
96
|
// Local log storage (opt-in): write solongate-audit.jsonl inside the user's
|
|
97
97
|
// chosen FOLDER. The audit hook does the ALLOW path; the guard does DENY (a
|
|
98
98
|
// blocked call never reaches PostToolUse). `security` is the resolved config.
|
|
99
|
+
/**
|
|
100
|
+
* Short, non-reversible mark of the account an entry belongs to.
|
|
101
|
+
*
|
|
102
|
+
* The machine-local log is one file, and nothing in a line said which account
|
|
103
|
+
* produced it, so after pairing a different account the viewers presented the
|
|
104
|
+
* previous one's calls as yours. Stamping each line lets a reader keep only its
|
|
105
|
+
* own without deleting anybody's history. It is a hash prefix, never the key.
|
|
106
|
+
*/
|
|
107
|
+
function accountMark() {
|
|
108
|
+
try {
|
|
109
|
+
return API_KEY ? createHash('sha256').update(API_KEY).digest('hex').slice(0, 16) : '';
|
|
110
|
+
} catch {
|
|
111
|
+
return '';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
99
115
|
function writeLocalLog(security, entry) {
|
|
100
116
|
try {
|
|
117
|
+
const mark = accountMark();
|
|
118
|
+
if (mark) entry = { ...entry, acct: mark };
|
|
101
119
|
const l = security && security.localLogs;
|
|
102
120
|
// The cloud POST is skipped whenever localLogsOnly() says this device is in
|
|
103
121
|
// local-only mode — and that answer can come from the persisted marker alone,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.82.
|
|
3
|
+
"version": "0.82.92",
|
|
4
4
|
"description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|