@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.
@@ -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();
@@ -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 hasKey = isAuthenticated();
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 || !hasKey;
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 isGuestAccount = rawEmail.endsWith("@anonymous.solongate.invalid");
5358
- const hasKey = isAuthenticated();
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 || !hasKey;
5414
+ const locked = accounts.length === 0;
5395
5415
  const effectiveSection = locked ? SETTINGS_SECTION : section;
5396
5416
  useInput8((input, key) => {
5397
5417
  if (help) {
@@ -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
- /** Empty the local log file. Returns how many lines were removed. */
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.88",
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": {