@solongate/proxy 0.82.88 → 0.82.90
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/api-client/client.d.ts +6 -0
- package/dist/commands/index.js +34 -0
- package/dist/index.js +52 -4
- package/dist/tui/index.js +58 -4
- package/dist/tui/local-log.d.ts +19 -1
- package/package.json +1 -1
|
@@ -28,6 +28,8 @@ export declare const GUEST_EMAIL_SUFFIX = "@anonymous.solongate.invalid";
|
|
|
28
28
|
* way the dashboard does rather than half-working here.
|
|
29
29
|
*/
|
|
30
30
|
export declare function isGuestAccount(): boolean;
|
|
31
|
+
/** The key this device enforces with, or null when it is not paired. */
|
|
32
|
+
export declare function enforcingKey(): string | null;
|
|
31
33
|
/** True when the given key is the ACTIVE one the guard hooks use. */
|
|
32
34
|
export declare function isActiveAccount(apiKey: string): boolean;
|
|
33
35
|
/**
|
|
@@ -54,6 +56,10 @@ export declare class ApiError extends Error {
|
|
|
54
56
|
readonly code: string;
|
|
55
57
|
constructor(status: number, code: string, message: string);
|
|
56
58
|
}
|
|
59
|
+
/** Raised when a guest account tries to change something. */
|
|
60
|
+
export declare class GuestReadOnlyError extends Error {
|
|
61
|
+
constructor();
|
|
62
|
+
}
|
|
57
63
|
/** Raised when no API key can be found — tells the user to run `solongate` and pair. */
|
|
58
64
|
export declare class NotAuthenticatedError extends Error {
|
|
59
65
|
constructor();
|
package/dist/commands/index.js
CHANGED
|
@@ -125,7 +125,31 @@ function codexHooksStatus() {
|
|
|
125
125
|
|
|
126
126
|
// src/api-client/client.ts
|
|
127
127
|
var DEFAULT_API_URL = "https://api.solongate.com";
|
|
128
|
+
var accountsFile = () => join2(homedir2(), ".solongate", "accounts.json");
|
|
129
|
+
function listAccounts() {
|
|
130
|
+
let list5 = [];
|
|
131
|
+
try {
|
|
132
|
+
const raw = JSON.parse(readFileSync2(accountsFile(), "utf-8"));
|
|
133
|
+
if (Array.isArray(raw)) list5 = raw.filter((a) => a && typeof a.apiKey === "string");
|
|
134
|
+
} catch {
|
|
135
|
+
}
|
|
136
|
+
const active2 = loginCredentialFile();
|
|
137
|
+
if (active2.apiKey && !list5.some((a) => a.apiKey === active2.apiKey)) {
|
|
138
|
+
list5.unshift({ apiKey: active2.apiKey, apiUrl: active2.apiUrl || DEFAULT_API_URL });
|
|
139
|
+
}
|
|
140
|
+
return list5;
|
|
141
|
+
}
|
|
128
142
|
var viewOverride = null;
|
|
143
|
+
var GUEST_EMAIL_SUFFIX = "@anonymous.solongate.invalid";
|
|
144
|
+
function isGuestAccount() {
|
|
145
|
+
try {
|
|
146
|
+
const active2 = loginCredentialFile().apiKey;
|
|
147
|
+
if (!active2) return false;
|
|
148
|
+
return listAccounts().some((a) => a.apiKey === active2 && (a.email ?? "").endsWith(GUEST_EMAIL_SUFFIX));
|
|
149
|
+
} catch {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
129
153
|
var ApiError = class extends Error {
|
|
130
154
|
status;
|
|
131
155
|
code;
|
|
@@ -136,6 +160,12 @@ var ApiError = class extends Error {
|
|
|
136
160
|
this.code = code;
|
|
137
161
|
}
|
|
138
162
|
};
|
|
163
|
+
var GuestReadOnlyError = class extends Error {
|
|
164
|
+
constructor() {
|
|
165
|
+
super("Guest account: sign up at auth.solongate.com to change anything. Your project, its policy and everything recorded carry over.");
|
|
166
|
+
this.name = "GuestReadOnlyError";
|
|
167
|
+
}
|
|
168
|
+
};
|
|
139
169
|
var NotAuthenticatedError = class extends Error {
|
|
140
170
|
constructor() {
|
|
141
171
|
super("Not logged in. Run `solongate` and log in from the Accounts panel.");
|
|
@@ -200,6 +230,9 @@ function buildUrl(base, path, query) {
|
|
|
200
230
|
return url.toString();
|
|
201
231
|
}
|
|
202
232
|
async function request(method, path, opts = {}) {
|
|
233
|
+
if (method !== "GET" && isGuestAccount()) {
|
|
234
|
+
throw new GuestReadOnlyError();
|
|
235
|
+
}
|
|
203
236
|
const creds = resolveCredentials(opts.apiUrl);
|
|
204
237
|
const url = buildUrl(creds.apiUrl, path, opts.query);
|
|
205
238
|
const headers = {
|
|
@@ -1149,6 +1182,7 @@ import { join as join4 } from "path";
|
|
|
1149
1182
|
// src/tui/local-log.ts
|
|
1150
1183
|
import { closeSync, existsSync as existsSync3, openSync, readdirSync, readFileSync as readFileSync4, readSync, statSync, writeFileSync as writeFileSync3 } from "fs";
|
|
1151
1184
|
import { homedir as homedir3 } from "os";
|
|
1185
|
+
import { createHash } from "crypto";
|
|
1152
1186
|
import { isAbsolute, join as join3 } from "path";
|
|
1153
1187
|
var DEFAULT_LOCAL_LOG = join3(homedir3(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
1154
1188
|
function localLogFile() {
|
package/dist/index.js
CHANGED
|
@@ -7404,6 +7404,7 @@ var init_components = __esm({
|
|
|
7404
7404
|
// src/tui/local-log.ts
|
|
7405
7405
|
import { closeSync, existsSync as existsSync4, openSync as openSync3, readdirSync, readFileSync as readFileSync8, readSync, statSync, writeFileSync as writeFileSync6 } from "fs";
|
|
7406
7406
|
import { homedir as homedir6 } from "os";
|
|
7407
|
+
import { createHash as createHash2 } from "crypto";
|
|
7407
7408
|
import { isAbsolute, join as join8 } from "path";
|
|
7408
7409
|
function localLogFile() {
|
|
7409
7410
|
try {
|
|
@@ -7435,6 +7436,30 @@ function localLogFile() {
|
|
|
7435
7436
|
}
|
|
7436
7437
|
return DEFAULT_LOCAL_LOG;
|
|
7437
7438
|
}
|
|
7439
|
+
function ensureLocalLogOwner(activeApiKey) {
|
|
7440
|
+
try {
|
|
7441
|
+
const marker = join8(homedir6(), ".solongate", "local-logs", ".owner");
|
|
7442
|
+
const want = activeApiKey ? createHash2("sha256").update(activeApiKey).digest("hex").slice(0, 16) : "";
|
|
7443
|
+
let have = "";
|
|
7444
|
+
try {
|
|
7445
|
+
have = readFileSync8(marker, "utf-8").trim();
|
|
7446
|
+
} catch {
|
|
7447
|
+
}
|
|
7448
|
+
if (have === want) return false;
|
|
7449
|
+
const cleared = have !== "" && localLogExists();
|
|
7450
|
+
if (cleared) clearLocalLog();
|
|
7451
|
+
try {
|
|
7452
|
+
writeFileSync6(marker, want);
|
|
7453
|
+
} catch {
|
|
7454
|
+
}
|
|
7455
|
+
return cleared;
|
|
7456
|
+
} catch {
|
|
7457
|
+
return false;
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7460
|
+
function localLogExists() {
|
|
7461
|
+
return existsSync4(localLogFile());
|
|
7462
|
+
}
|
|
7438
7463
|
function tailLines(file, maxBytes = 131072) {
|
|
7439
7464
|
try {
|
|
7440
7465
|
const size = statSync(file).size;
|
|
@@ -7523,8 +7548,10 @@ __export(client_exports, {
|
|
|
7523
7548
|
ApiError: () => ApiError,
|
|
7524
7549
|
DEFAULT_API_URL: () => DEFAULT_API_URL2,
|
|
7525
7550
|
GUEST_EMAIL_SUFFIX: () => GUEST_EMAIL_SUFFIX,
|
|
7551
|
+
GuestReadOnlyError: () => GuestReadOnlyError,
|
|
7526
7552
|
NotAuthenticatedError: () => NotAuthenticatedError,
|
|
7527
7553
|
clearActiveCredential: () => clearActiveCredential,
|
|
7554
|
+
enforcingKey: () => enforcingKey,
|
|
7528
7555
|
isActiveAccount: () => isActiveAccount,
|
|
7529
7556
|
isAuthenticated: () => isAuthenticated,
|
|
7530
7557
|
isGuestAccount: () => isGuestAccount,
|
|
@@ -7596,6 +7623,9 @@ function isGuestAccount() {
|
|
|
7596
7623
|
return false;
|
|
7597
7624
|
}
|
|
7598
7625
|
}
|
|
7626
|
+
function enforcingKey() {
|
|
7627
|
+
return loginCredentialFile().apiKey ?? null;
|
|
7628
|
+
}
|
|
7599
7629
|
function isActiveAccount(apiKey) {
|
|
7600
7630
|
return loginCredentialFile().apiKey === apiKey;
|
|
7601
7631
|
}
|
|
@@ -7695,6 +7725,9 @@ function buildUrl(base, path, query) {
|
|
|
7695
7725
|
return url.toString();
|
|
7696
7726
|
}
|
|
7697
7727
|
async function request(method, path, opts = {}) {
|
|
7728
|
+
if (method !== "GET" && isGuestAccount()) {
|
|
7729
|
+
throw new GuestReadOnlyError();
|
|
7730
|
+
}
|
|
7698
7731
|
const creds = resolveCredentials(opts.apiUrl);
|
|
7699
7732
|
const url = buildUrl(creds.apiUrl, path, opts.query);
|
|
7700
7733
|
const headers = {
|
|
@@ -7750,7 +7783,7 @@ async function request(method, path, opts = {}) {
|
|
|
7750
7783
|
}
|
|
7751
7784
|
return json;
|
|
7752
7785
|
}
|
|
7753
|
-
var DEFAULT_API_URL2, accountsFile, viewOverride, GUEST_EMAIL_SUFFIX, ApiError, NotAuthenticatedError, cached2;
|
|
7786
|
+
var DEFAULT_API_URL2, accountsFile, viewOverride, GUEST_EMAIL_SUFFIX, ApiError, GuestReadOnlyError, NotAuthenticatedError, cached2;
|
|
7754
7787
|
var init_client = __esm({
|
|
7755
7788
|
"src/api-client/client.ts"() {
|
|
7756
7789
|
"use strict";
|
|
@@ -7769,6 +7802,12 @@ var init_client = __esm({
|
|
|
7769
7802
|
this.code = code;
|
|
7770
7803
|
}
|
|
7771
7804
|
};
|
|
7805
|
+
GuestReadOnlyError = class extends Error {
|
|
7806
|
+
constructor() {
|
|
7807
|
+
super("Guest account: sign up at auth.solongate.com to change anything. Your project, its policy and everything recorded carry over.");
|
|
7808
|
+
this.name = "GuestReadOnlyError";
|
|
7809
|
+
}
|
|
7810
|
+
};
|
|
7772
7811
|
NotAuthenticatedError = class extends Error {
|
|
7773
7812
|
constructor() {
|
|
7774
7813
|
super("Not logged in. Run `solongate` and log in from the Accounts panel.");
|
|
@@ -11741,6 +11780,7 @@ function SettingsPanel({
|
|
|
11741
11780
|
else if (inp === "m") {
|
|
11742
11781
|
if (cur.kind === "acct") {
|
|
11743
11782
|
const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
|
|
11783
|
+
if (ok) clearLocalLog();
|
|
11744
11784
|
setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
|
|
11745
11785
|
refreshAccounts();
|
|
11746
11786
|
} else if (cur.kind === "wh" || cur.kind === "alert" || cur.kind === "self" || cur.kind === "ll-enabled" || cur.kind === "ll-server") {
|
|
@@ -11760,6 +11800,7 @@ function SettingsPanel({
|
|
|
11760
11800
|
}
|
|
11761
11801
|
setConfirmDel(null);
|
|
11762
11802
|
removeAccount(target.apiKey);
|
|
11803
|
+
clearLocalLog();
|
|
11763
11804
|
let extra = " from this device";
|
|
11764
11805
|
if (wasActive) {
|
|
11765
11806
|
if (others.length) {
|
|
@@ -12107,6 +12148,7 @@ var init_Settings = __esm({
|
|
|
12107
12148
|
init_components();
|
|
12108
12149
|
init_hooks();
|
|
12109
12150
|
init_theme();
|
|
12151
|
+
init_local_log();
|
|
12110
12152
|
EVENTS = ["denials", "allowed", "all"];
|
|
12111
12153
|
SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
12112
12154
|
SIGNALS2 = ["any", "deny", "dlp", "ratelimit"];
|
|
@@ -12190,8 +12232,7 @@ function App() {
|
|
|
12190
12232
|
const cur = accounts[acctIdx];
|
|
12191
12233
|
const rawEmail = cur?.email ?? "";
|
|
12192
12234
|
const isGuestAccount2 = rawEmail.endsWith("@anonymous.solongate.invalid");
|
|
12193
|
-
const
|
|
12194
|
-
const acctLabel2 = !cur ? "not logged in" : !hasKey ? "signed out" : isGuestAccount2 ? "Anonymous" : rawEmail || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}`;
|
|
12235
|
+
const acctLabel2 = !cur ? "not logged in" : isGuestAccount2 ? "Anonymous" : rawEmail || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}`;
|
|
12195
12236
|
useEffect8(() => {
|
|
12196
12237
|
if (!cur || cur.email) return;
|
|
12197
12238
|
let alive = true;
|
|
@@ -12226,7 +12267,13 @@ function App() {
|
|
|
12226
12267
|
setViewKey(next?.apiKey);
|
|
12227
12268
|
setViewNonce((n) => n + 1);
|
|
12228
12269
|
};
|
|
12229
|
-
|
|
12270
|
+
useEffect8(() => {
|
|
12271
|
+
try {
|
|
12272
|
+
ensureLocalLogOwner(enforcingKey());
|
|
12273
|
+
} catch {
|
|
12274
|
+
}
|
|
12275
|
+
}, [accounts.length]);
|
|
12276
|
+
const locked = accounts.length === 0;
|
|
12230
12277
|
const effectiveSection = locked ? SETTINGS_SECTION : section;
|
|
12231
12278
|
useInput8((input, key) => {
|
|
12232
12279
|
if (help) {
|
|
@@ -12317,6 +12364,7 @@ var init_App = __esm({
|
|
|
12317
12364
|
init_nav();
|
|
12318
12365
|
init_client();
|
|
12319
12366
|
init_api_client();
|
|
12367
|
+
init_local_log();
|
|
12320
12368
|
init_self_update();
|
|
12321
12369
|
SECTIONS = [
|
|
12322
12370
|
{ label: "Live", Panel: LiveHint },
|
package/dist/tui/index.js
CHANGED
|
@@ -738,6 +738,7 @@ import { join as join5 } from "path";
|
|
|
738
738
|
// src/tui/local-log.ts
|
|
739
739
|
import { closeSync, existsSync, openSync, readdirSync, readFileSync as readFileSync2, readSync, statSync, writeFileSync } from "fs";
|
|
740
740
|
import { homedir as homedir2 } from "os";
|
|
741
|
+
import { createHash } from "crypto";
|
|
741
742
|
import { isAbsolute, join as join2 } from "path";
|
|
742
743
|
var DEFAULT_LOCAL_LOG = join2(homedir2(), ".solongate", "local-logs", "solongate-audit.jsonl");
|
|
743
744
|
function localLogFile() {
|
|
@@ -771,6 +772,30 @@ function localLogFile() {
|
|
|
771
772
|
return DEFAULT_LOCAL_LOG;
|
|
772
773
|
}
|
|
773
774
|
var LOCAL_LOG = localLogFile();
|
|
775
|
+
function ensureLocalLogOwner(activeApiKey) {
|
|
776
|
+
try {
|
|
777
|
+
const marker = join2(homedir2(), ".solongate", "local-logs", ".owner");
|
|
778
|
+
const want = activeApiKey ? createHash("sha256").update(activeApiKey).digest("hex").slice(0, 16) : "";
|
|
779
|
+
let have = "";
|
|
780
|
+
try {
|
|
781
|
+
have = readFileSync2(marker, "utf-8").trim();
|
|
782
|
+
} catch {
|
|
783
|
+
}
|
|
784
|
+
if (have === want) return false;
|
|
785
|
+
const cleared = have !== "" && localLogExists();
|
|
786
|
+
if (cleared) clearLocalLog();
|
|
787
|
+
try {
|
|
788
|
+
writeFileSync(marker, want);
|
|
789
|
+
} catch {
|
|
790
|
+
}
|
|
791
|
+
return cleared;
|
|
792
|
+
} catch {
|
|
793
|
+
return false;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function localLogExists() {
|
|
797
|
+
return existsSync(localLogFile());
|
|
798
|
+
}
|
|
774
799
|
function tailLines(file, maxBytes = 131072) {
|
|
775
800
|
try {
|
|
776
801
|
const size = statSync(file).size;
|
|
@@ -904,6 +929,19 @@ function setViewCredentials(creds) {
|
|
|
904
929
|
viewOverride = creds;
|
|
905
930
|
cached2 = null;
|
|
906
931
|
}
|
|
932
|
+
var GUEST_EMAIL_SUFFIX = "@anonymous.solongate.invalid";
|
|
933
|
+
function isGuestAccount() {
|
|
934
|
+
try {
|
|
935
|
+
const active2 = loginCredentialFile().apiKey;
|
|
936
|
+
if (!active2) return false;
|
|
937
|
+
return listAccounts().some((a) => a.apiKey === active2 && (a.email ?? "").endsWith(GUEST_EMAIL_SUFFIX));
|
|
938
|
+
} catch {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
function enforcingKey() {
|
|
943
|
+
return loginCredentialFile().apiKey ?? null;
|
|
944
|
+
}
|
|
907
945
|
function isActiveAccount(apiKey) {
|
|
908
946
|
return loginCredentialFile().apiKey === apiKey;
|
|
909
947
|
}
|
|
@@ -956,6 +994,12 @@ var ApiError = class extends Error {
|
|
|
956
994
|
this.code = code;
|
|
957
995
|
}
|
|
958
996
|
};
|
|
997
|
+
var GuestReadOnlyError = class extends Error {
|
|
998
|
+
constructor() {
|
|
999
|
+
super("Guest account: sign up at auth.solongate.com to change anything. Your project, its policy and everything recorded carry over.");
|
|
1000
|
+
this.name = "GuestReadOnlyError";
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
959
1003
|
var NotAuthenticatedError = class extends Error {
|
|
960
1004
|
constructor() {
|
|
961
1005
|
super("Not logged in. Run `solongate` and log in from the Accounts panel.");
|
|
@@ -1020,6 +1064,9 @@ function buildUrl(base, path, query) {
|
|
|
1020
1064
|
return url.toString();
|
|
1021
1065
|
}
|
|
1022
1066
|
async function request(method, path, opts = {}) {
|
|
1067
|
+
if (method !== "GET" && isGuestAccount()) {
|
|
1068
|
+
throw new GuestReadOnlyError();
|
|
1069
|
+
}
|
|
1023
1070
|
const creds = resolveCredentials(opts.apiUrl);
|
|
1024
1071
|
const url = buildUrl(creds.apiUrl, path, opts.query);
|
|
1025
1072
|
const headers = {
|
|
@@ -4929,6 +4976,7 @@ function SettingsPanel({
|
|
|
4929
4976
|
else if (inp === "m") {
|
|
4930
4977
|
if (cur.kind === "acct") {
|
|
4931
4978
|
const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
|
|
4979
|
+
if (ok) clearLocalLog();
|
|
4932
4980
|
setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
|
|
4933
4981
|
refreshAccounts();
|
|
4934
4982
|
} else if (cur.kind === "wh" || cur.kind === "alert" || cur.kind === "self" || cur.kind === "ll-enabled" || cur.kind === "ll-server") {
|
|
@@ -4948,6 +4996,7 @@ function SettingsPanel({
|
|
|
4948
4996
|
}
|
|
4949
4997
|
setConfirmDel(null);
|
|
4950
4998
|
removeAccount(target.apiKey);
|
|
4999
|
+
clearLocalLog();
|
|
4951
5000
|
let extra = " from this device";
|
|
4952
5001
|
if (wasActive) {
|
|
4953
5002
|
if (others.length) {
|
|
@@ -5354,9 +5403,8 @@ function App() {
|
|
|
5354
5403
|
const acctIdx = Math.max(0, accounts.findIndex((a) => a.apiKey === viewKey));
|
|
5355
5404
|
const cur = accounts[acctIdx];
|
|
5356
5405
|
const rawEmail = cur?.email ?? "";
|
|
5357
|
-
const
|
|
5358
|
-
const
|
|
5359
|
-
const acctLabel2 = !cur ? "not logged in" : !hasKey ? "signed out" : isGuestAccount ? "Anonymous" : rawEmail || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}`;
|
|
5406
|
+
const isGuestAccount2 = rawEmail.endsWith("@anonymous.solongate.invalid");
|
|
5407
|
+
const acctLabel2 = !cur ? "not logged in" : isGuestAccount2 ? "Anonymous" : rawEmail || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}`;
|
|
5360
5408
|
useEffect8(() => {
|
|
5361
5409
|
if (!cur || cur.email) return;
|
|
5362
5410
|
let alive = true;
|
|
@@ -5391,7 +5439,13 @@ function App() {
|
|
|
5391
5439
|
setViewKey(next?.apiKey);
|
|
5392
5440
|
setViewNonce((n) => n + 1);
|
|
5393
5441
|
};
|
|
5394
|
-
|
|
5442
|
+
useEffect8(() => {
|
|
5443
|
+
try {
|
|
5444
|
+
ensureLocalLogOwner(enforcingKey());
|
|
5445
|
+
} catch {
|
|
5446
|
+
}
|
|
5447
|
+
}, [accounts.length]);
|
|
5448
|
+
const locked = accounts.length === 0;
|
|
5395
5449
|
const effectiveSection = locked ? SETTINGS_SECTION : section;
|
|
5396
5450
|
useInput8((input, key) => {
|
|
5397
5451
|
if (help) {
|
package/dist/tui/local-log.d.ts
CHANGED
|
@@ -23,6 +23,18 @@ export declare function localLogFile(): string;
|
|
|
23
23
|
export declare const LOCAL_LOG: string;
|
|
24
24
|
/** True when the resolved file exists — viewers use it to say "no entries yet"
|
|
25
25
|
* instead of pointing at a path that was never written. */
|
|
26
|
+
/**
|
|
27
|
+
* Make sure the local log belongs to the account now in use.
|
|
28
|
+
*
|
|
29
|
+
* The file is one per machine and no entry records which account produced it,
|
|
30
|
+
* so after pairing a different account the previous one's calls were still
|
|
31
|
+
* sitting in Live. Clearing on an in-app account switch was not enough: the
|
|
32
|
+
* account can change by pairing a new device, by signing out, or from the
|
|
33
|
+
* dashboard. A marker beside the log records whose it is (a hash, never the
|
|
34
|
+
* key itself); when that stops matching, the file is not ours and is started
|
|
35
|
+
* over. Returns true when it cleared.
|
|
36
|
+
*/
|
|
37
|
+
export declare function ensureLocalLogOwner(activeApiKey: string | null | undefined): boolean;
|
|
26
38
|
export declare function localLogExists(): boolean;
|
|
27
39
|
/** Read the last `maxBytes` of a file as complete lines (first partial dropped). */
|
|
28
40
|
export declare function tailLines(file: string, maxBytes?: number): string[];
|
|
@@ -44,7 +56,13 @@ export interface LocalLogLine {
|
|
|
44
56
|
}
|
|
45
57
|
/** Delete ONE matching line (ts + tool [+ session]) from the local log file. */
|
|
46
58
|
export declare function deleteLocalEntry(at: number, tool: string, session?: string | null): number;
|
|
47
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Empty the local log file. Returns how many lines were removed.
|
|
61
|
+
*
|
|
62
|
+
* The file is one per machine, not one per account, and nothing in an entry
|
|
63
|
+
* says which account produced it — so when the account changes, the honest move
|
|
64
|
+
* is to start it over rather than keep showing another account's calls in Live.
|
|
65
|
+
*/
|
|
48
66
|
export declare function clearLocalLog(): number;
|
|
49
67
|
/** DLP pattern name + rate-limit-burst flag derived from a decision's reason. */
|
|
50
68
|
export declare function reasonSignals(reason: string | null | undefined): {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.82.
|
|
3
|
+
"version": "0.82.90",
|
|
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": {
|