@solongate/proxy 0.82.88 → 0.82.89
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 +4 -0
- package/dist/commands/index.js +33 -0
- package/dist/index.js +16 -4
- package/dist/tui/index.js +24 -4
- package/dist/tui/local-log.d.ts +7 -1
- package/package.json +1 -1
|
@@ -54,6 +54,10 @@ export declare class ApiError extends Error {
|
|
|
54
54
|
readonly code: string;
|
|
55
55
|
constructor(status: number, code: string, message: string);
|
|
56
56
|
}
|
|
57
|
+
/** Raised when a guest account tries to change something. */
|
|
58
|
+
export declare class GuestReadOnlyError extends Error {
|
|
59
|
+
constructor();
|
|
60
|
+
}
|
|
57
61
|
/** Raised when no API key can be found — tells the user to run `solongate` and pair. */
|
|
58
62
|
export declare class NotAuthenticatedError extends Error {
|
|
59
63
|
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 = {
|
package/dist/index.js
CHANGED
|
@@ -7523,6 +7523,7 @@ __export(client_exports, {
|
|
|
7523
7523
|
ApiError: () => ApiError,
|
|
7524
7524
|
DEFAULT_API_URL: () => DEFAULT_API_URL2,
|
|
7525
7525
|
GUEST_EMAIL_SUFFIX: () => GUEST_EMAIL_SUFFIX,
|
|
7526
|
+
GuestReadOnlyError: () => GuestReadOnlyError,
|
|
7526
7527
|
NotAuthenticatedError: () => NotAuthenticatedError,
|
|
7527
7528
|
clearActiveCredential: () => clearActiveCredential,
|
|
7528
7529
|
isActiveAccount: () => isActiveAccount,
|
|
@@ -7695,6 +7696,9 @@ function buildUrl(base, path, query) {
|
|
|
7695
7696
|
return url.toString();
|
|
7696
7697
|
}
|
|
7697
7698
|
async function request(method, path, opts = {}) {
|
|
7699
|
+
if (method !== "GET" && isGuestAccount()) {
|
|
7700
|
+
throw new GuestReadOnlyError();
|
|
7701
|
+
}
|
|
7698
7702
|
const creds = resolveCredentials(opts.apiUrl);
|
|
7699
7703
|
const url = buildUrl(creds.apiUrl, path, opts.query);
|
|
7700
7704
|
const headers = {
|
|
@@ -7750,7 +7754,7 @@ async function request(method, path, opts = {}) {
|
|
|
7750
7754
|
}
|
|
7751
7755
|
return json;
|
|
7752
7756
|
}
|
|
7753
|
-
var DEFAULT_API_URL2, accountsFile, viewOverride, GUEST_EMAIL_SUFFIX, ApiError, NotAuthenticatedError, cached2;
|
|
7757
|
+
var DEFAULT_API_URL2, accountsFile, viewOverride, GUEST_EMAIL_SUFFIX, ApiError, GuestReadOnlyError, NotAuthenticatedError, cached2;
|
|
7754
7758
|
var init_client = __esm({
|
|
7755
7759
|
"src/api-client/client.ts"() {
|
|
7756
7760
|
"use strict";
|
|
@@ -7769,6 +7773,12 @@ var init_client = __esm({
|
|
|
7769
7773
|
this.code = code;
|
|
7770
7774
|
}
|
|
7771
7775
|
};
|
|
7776
|
+
GuestReadOnlyError = class extends Error {
|
|
7777
|
+
constructor() {
|
|
7778
|
+
super("Guest account: sign up at auth.solongate.com to change anything. Your project, its policy and everything recorded carry over.");
|
|
7779
|
+
this.name = "GuestReadOnlyError";
|
|
7780
|
+
}
|
|
7781
|
+
};
|
|
7772
7782
|
NotAuthenticatedError = class extends Error {
|
|
7773
7783
|
constructor() {
|
|
7774
7784
|
super("Not logged in. Run `solongate` and log in from the Accounts panel.");
|
|
@@ -11741,6 +11751,7 @@ function SettingsPanel({
|
|
|
11741
11751
|
else if (inp === "m") {
|
|
11742
11752
|
if (cur.kind === "acct") {
|
|
11743
11753
|
const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
|
|
11754
|
+
if (ok) clearLocalLog();
|
|
11744
11755
|
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
11756
|
refreshAccounts();
|
|
11746
11757
|
} else if (cur.kind === "wh" || cur.kind === "alert" || cur.kind === "self" || cur.kind === "ll-enabled" || cur.kind === "ll-server") {
|
|
@@ -11760,6 +11771,7 @@ function SettingsPanel({
|
|
|
11760
11771
|
}
|
|
11761
11772
|
setConfirmDel(null);
|
|
11762
11773
|
removeAccount(target.apiKey);
|
|
11774
|
+
clearLocalLog();
|
|
11763
11775
|
let extra = " from this device";
|
|
11764
11776
|
if (wasActive) {
|
|
11765
11777
|
if (others.length) {
|
|
@@ -12107,6 +12119,7 @@ var init_Settings = __esm({
|
|
|
12107
12119
|
init_components();
|
|
12108
12120
|
init_hooks();
|
|
12109
12121
|
init_theme();
|
|
12122
|
+
init_local_log();
|
|
12110
12123
|
EVENTS = ["denials", "allowed", "all"];
|
|
12111
12124
|
SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
12112
12125
|
SIGNALS2 = ["any", "deny", "dlp", "ratelimit"];
|
|
@@ -12190,8 +12203,7 @@ function App() {
|
|
|
12190
12203
|
const cur = accounts[acctIdx];
|
|
12191
12204
|
const rawEmail = cur?.email ?? "";
|
|
12192
12205
|
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)}`;
|
|
12206
|
+
const acctLabel2 = !cur ? "not logged in" : isGuestAccount2 ? "Anonymous" : rawEmail || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}`;
|
|
12195
12207
|
useEffect8(() => {
|
|
12196
12208
|
if (!cur || cur.email) return;
|
|
12197
12209
|
let alive = true;
|
|
@@ -12226,7 +12238,7 @@ function App() {
|
|
|
12226
12238
|
setViewKey(next?.apiKey);
|
|
12227
12239
|
setViewNonce((n) => n + 1);
|
|
12228
12240
|
};
|
|
12229
|
-
const locked = accounts.length === 0
|
|
12241
|
+
const locked = accounts.length === 0;
|
|
12230
12242
|
const effectiveSection = locked ? SETTINGS_SECTION : section;
|
|
12231
12243
|
useInput8((input, key) => {
|
|
12232
12244
|
if (help) {
|
package/dist/tui/index.js
CHANGED
|
@@ -904,6 +904,16 @@ function setViewCredentials(creds) {
|
|
|
904
904
|
viewOverride = creds;
|
|
905
905
|
cached2 = null;
|
|
906
906
|
}
|
|
907
|
+
var GUEST_EMAIL_SUFFIX = "@anonymous.solongate.invalid";
|
|
908
|
+
function isGuestAccount() {
|
|
909
|
+
try {
|
|
910
|
+
const active2 = loginCredentialFile().apiKey;
|
|
911
|
+
if (!active2) return false;
|
|
912
|
+
return listAccounts().some((a) => a.apiKey === active2 && (a.email ?? "").endsWith(GUEST_EMAIL_SUFFIX));
|
|
913
|
+
} catch {
|
|
914
|
+
return false;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
907
917
|
function isActiveAccount(apiKey) {
|
|
908
918
|
return loginCredentialFile().apiKey === apiKey;
|
|
909
919
|
}
|
|
@@ -956,6 +966,12 @@ var ApiError = class extends Error {
|
|
|
956
966
|
this.code = code;
|
|
957
967
|
}
|
|
958
968
|
};
|
|
969
|
+
var GuestReadOnlyError = class extends Error {
|
|
970
|
+
constructor() {
|
|
971
|
+
super("Guest account: sign up at auth.solongate.com to change anything. Your project, its policy and everything recorded carry over.");
|
|
972
|
+
this.name = "GuestReadOnlyError";
|
|
973
|
+
}
|
|
974
|
+
};
|
|
959
975
|
var NotAuthenticatedError = class extends Error {
|
|
960
976
|
constructor() {
|
|
961
977
|
super("Not logged in. Run `solongate` and log in from the Accounts panel.");
|
|
@@ -1020,6 +1036,9 @@ function buildUrl(base, path, query) {
|
|
|
1020
1036
|
return url.toString();
|
|
1021
1037
|
}
|
|
1022
1038
|
async function request(method, path, opts = {}) {
|
|
1039
|
+
if (method !== "GET" && isGuestAccount()) {
|
|
1040
|
+
throw new GuestReadOnlyError();
|
|
1041
|
+
}
|
|
1023
1042
|
const creds = resolveCredentials(opts.apiUrl);
|
|
1024
1043
|
const url = buildUrl(creds.apiUrl, path, opts.query);
|
|
1025
1044
|
const headers = {
|
|
@@ -4929,6 +4948,7 @@ function SettingsPanel({
|
|
|
4929
4948
|
else if (inp === "m") {
|
|
4930
4949
|
if (cur.kind === "acct") {
|
|
4931
4950
|
const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
|
|
4951
|
+
if (ok) clearLocalLog();
|
|
4932
4952
|
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
4953
|
refreshAccounts();
|
|
4934
4954
|
} else if (cur.kind === "wh" || cur.kind === "alert" || cur.kind === "self" || cur.kind === "ll-enabled" || cur.kind === "ll-server") {
|
|
@@ -4948,6 +4968,7 @@ function SettingsPanel({
|
|
|
4948
4968
|
}
|
|
4949
4969
|
setConfirmDel(null);
|
|
4950
4970
|
removeAccount(target.apiKey);
|
|
4971
|
+
clearLocalLog();
|
|
4951
4972
|
let extra = " from this device";
|
|
4952
4973
|
if (wasActive) {
|
|
4953
4974
|
if (others.length) {
|
|
@@ -5354,9 +5375,8 @@ function App() {
|
|
|
5354
5375
|
const acctIdx = Math.max(0, accounts.findIndex((a) => a.apiKey === viewKey));
|
|
5355
5376
|
const cur = accounts[acctIdx];
|
|
5356
5377
|
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)}`;
|
|
5378
|
+
const isGuestAccount2 = rawEmail.endsWith("@anonymous.solongate.invalid");
|
|
5379
|
+
const acctLabel2 = !cur ? "not logged in" : isGuestAccount2 ? "Anonymous" : rawEmail || cur.user || cur.project || `account \u2026${cur.apiKey.slice(-4)}`;
|
|
5360
5380
|
useEffect8(() => {
|
|
5361
5381
|
if (!cur || cur.email) return;
|
|
5362
5382
|
let alive = true;
|
|
@@ -5391,7 +5411,7 @@ function App() {
|
|
|
5391
5411
|
setViewKey(next?.apiKey);
|
|
5392
5412
|
setViewNonce((n) => n + 1);
|
|
5393
5413
|
};
|
|
5394
|
-
const locked = accounts.length === 0
|
|
5414
|
+
const locked = accounts.length === 0;
|
|
5395
5415
|
const effectiveSection = locked ? SETTINGS_SECTION : section;
|
|
5396
5416
|
useInput8((input, key) => {
|
|
5397
5417
|
if (help) {
|
package/dist/tui/local-log.d.ts
CHANGED
|
@@ -44,7 +44,13 @@ export interface LocalLogLine {
|
|
|
44
44
|
}
|
|
45
45
|
/** Delete ONE matching line (ts + tool [+ session]) from the local log file. */
|
|
46
46
|
export declare function deleteLocalEntry(at: number, tool: string, session?: string | null): number;
|
|
47
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Empty the local log file. Returns how many lines were removed.
|
|
49
|
+
*
|
|
50
|
+
* The file is one per machine, not one per account, and nothing in an entry
|
|
51
|
+
* says which account produced it — so when the account changes, the honest move
|
|
52
|
+
* is to start it over rather than keep showing another account's calls in Live.
|
|
53
|
+
*/
|
|
48
54
|
export declare function clearLocalLog(): number;
|
|
49
55
|
/** DLP pattern name + rate-limit-burst flag derived from a decision's reason. */
|
|
50
56
|
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.89",
|
|
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": {
|