@solongate/proxy 0.82.89 → 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.
@@ -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
  /**
@@ -1182,6 +1182,7 @@ import { join as join4 } from "path";
1182
1182
  // src/tui/local-log.ts
1183
1183
  import { closeSync, existsSync as existsSync3, openSync, readdirSync, readFileSync as readFileSync4, readSync, statSync, writeFileSync as writeFileSync3 } from "fs";
1184
1184
  import { homedir as homedir3 } from "os";
1185
+ import { createHash } from "crypto";
1185
1186
  import { isAbsolute, join as join3 } from "path";
1186
1187
  var DEFAULT_LOCAL_LOG = join3(homedir3(), ".solongate", "local-logs", "solongate-audit.jsonl");
1187
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;
@@ -7526,6 +7551,7 @@ __export(client_exports, {
7526
7551
  GuestReadOnlyError: () => GuestReadOnlyError,
7527
7552
  NotAuthenticatedError: () => NotAuthenticatedError,
7528
7553
  clearActiveCredential: () => clearActiveCredential,
7554
+ enforcingKey: () => enforcingKey,
7529
7555
  isActiveAccount: () => isActiveAccount,
7530
7556
  isAuthenticated: () => isAuthenticated,
7531
7557
  isGuestAccount: () => isGuestAccount,
@@ -7597,6 +7623,9 @@ function isGuestAccount() {
7597
7623
  return false;
7598
7624
  }
7599
7625
  }
7626
+ function enforcingKey() {
7627
+ return loginCredentialFile().apiKey ?? null;
7628
+ }
7600
7629
  function isActiveAccount(apiKey) {
7601
7630
  return loginCredentialFile().apiKey === apiKey;
7602
7631
  }
@@ -12238,6 +12267,12 @@ function App() {
12238
12267
  setViewKey(next?.apiKey);
12239
12268
  setViewNonce((n) => n + 1);
12240
12269
  };
12270
+ useEffect8(() => {
12271
+ try {
12272
+ ensureLocalLogOwner(enforcingKey());
12273
+ } catch {
12274
+ }
12275
+ }, [accounts.length]);
12241
12276
  const locked = accounts.length === 0;
12242
12277
  const effectiveSection = locked ? SETTINGS_SECTION : section;
12243
12278
  useInput8((input, key) => {
@@ -12329,6 +12364,7 @@ var init_App = __esm({
12329
12364
  init_nav();
12330
12365
  init_client();
12331
12366
  init_api_client();
12367
+ init_local_log();
12332
12368
  init_self_update();
12333
12369
  SECTIONS = [
12334
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;
@@ -914,6 +939,9 @@ function isGuestAccount() {
914
939
  return false;
915
940
  }
916
941
  }
942
+ function enforcingKey() {
943
+ return loginCredentialFile().apiKey ?? null;
944
+ }
917
945
  function isActiveAccount(apiKey) {
918
946
  return loginCredentialFile().apiKey === apiKey;
919
947
  }
@@ -5411,6 +5439,12 @@ function App() {
5411
5439
  setViewKey(next?.apiKey);
5412
5440
  setViewNonce((n) => n + 1);
5413
5441
  };
5442
+ useEffect8(() => {
5443
+ try {
5444
+ ensureLocalLogOwner(enforcingKey());
5445
+ } catch {
5446
+ }
5447
+ }, [accounts.length]);
5414
5448
  const locked = accounts.length === 0;
5415
5449
  const effectiveSection = locked ? SETTINGS_SECTION : section;
5416
5450
  useInput8((input, key) => {
@@ -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[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.82.89",
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": {