sigrank 1.0.31 → 1.0.33

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/index.mjs CHANGED
@@ -56,13 +56,14 @@ function serverVersion() {
56
56
  // than hanging on a broken connection.
57
57
  process.on("uncaughtException", (err) => {
58
58
  process.stderr.write(
59
- `[sigrank-mcp] uncaughtException: ${err?.stack || err}\n`,
59
+ `[sigrank-mcp] uncaughtException: ${err?.message || err}\n`,
60
60
  );
61
61
  process.exit(1);
62
62
  });
63
63
  process.on("unhandledRejection", (reason) => {
64
+ const msg = reason instanceof Error ? reason.message : String(reason);
64
65
  process.stderr.write(
65
- `[sigrank-mcp] unhandledRejection: ${reason?.stack || reason}\n`,
66
+ `[sigrank-mcp] unhandledRejection: ${msg}\n`,
66
67
  );
67
68
  process.exit(1);
68
69
  });
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://raw.githubusercontent.com/anthropics/mcpb/main/schemas/mcpb-manifest-v0.4.schema.json",
3
3
  "manifest_version": "0.4",
4
4
  "name": "sigrank",
5
- "version": "1.0.30",
5
+ "version": "1.0.32",
6
6
  "description": "Ranks AI coding operators by token cascade efficiency (Yield = cache_read \u00d7 output / input\u00b2). 25 tools including SigRank Standard record, yield calculation, local token usage pulls, signed submission, and tokscale-powered analytics (market share, developer profiles, model trends, cost analysis, device profiles, MCP usage, competitive intelligence). Privacy-first: runs locally, only four token counts leave the machine.",
7
7
  "author": {
8
8
  "name": "SunrisesIllNeverSee",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigrank",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "author": "SunrisesIllNeverSee (https://github.com/SunrisesIllNeverSee)",
5
5
  "description": "Upsilon measurement engine distributed through the sigrank CLI/MCP compatibility package, with SigRank public leaderboard tools.",
6
6
  "mcpName": "io.github.SunrisesIllNeverSee/sigrank-mcp",
@@ -87,12 +87,12 @@
87
87
  "@modelcontextprotocol/sdk": "^1.0.0",
88
88
  "token-cascade": "^0.2.1",
89
89
  "ccusage": "^20.0.19",
90
- "tokscale": "^4.7.0",
91
- "tteop-spec": "0.1.5-draft"
90
+ "tokscale": "^4.7.0"
92
91
  },
93
92
  "devDependencies": {
94
93
  "@resvg/resvg-js": "^2.6.2",
95
- "gifenc": "^1.0.3"
94
+ "gifenc": "^1.0.3",
95
+ "tteop-spec": "0.1.5-draft"
96
96
  },
97
97
  "overrides": {
98
98
  "@hono/node-server": "^2.0.5"
package/submit/index.mjs CHANGED
@@ -12,6 +12,7 @@
12
12
  import { snapshotHash, signPayload } from "../identity/sign.mjs";
13
13
  import { preflight } from "./preflight.mjs";
14
14
  import { pkgVersion } from "../lib/pkg-version.mjs";
15
+ import { validateApiBase } from "../tools/_helpers.mjs";
15
16
  import {
16
17
  TERMS_VERSION,
17
18
  PRIVACY_VERSION,
@@ -179,8 +180,9 @@ export async function submitSignedWindow(
179
180
  };
180
181
  }
181
182
 
182
- const apiBase =
183
- opts.apiBase || process.env.SIGRANK_API_BASE || "https://signalaf.com";
183
+ const apiBase = validateApiBase(
184
+ opts.apiBase || process.env.SIGRANK_API_BASE || "https://signalaf.com",
185
+ );
184
186
  // FIX M: default a 15s AbortController timeout when the caller doesn't inject a
185
187
  // fetchImpl. The TUI path already wraps fetch (callTool → doFetch, 10s), but the
186
188
  // legacy CLI `watch --submit` + the CLI default-view [S] call submitSignedWindow
@@ -25,6 +25,32 @@ const _envPath = `${_localBin}${process.env.PATH ? ":" + process.env.PATH : ""}`
25
25
 
26
26
  export const DEFAULT_API_BASE =
27
27
  process.env.SIGRANK_API_BASE || "https://signalaf.com";
28
+
29
+ /** Allowed API hosts — prevents SSRF via SIGRANK_API_BASE override. */
30
+ const ALLOWED_API_HOSTS = new Set([
31
+ "signalaf.com",
32
+ "sigeconomy.com",
33
+ "localhost",
34
+ "127.0.0.1",
35
+ "test.local", // test fixtures only
36
+ ]);
37
+
38
+ /** Validate that a URL points to an allowed API host. */
39
+ export function validateApiBase(urlStr) {
40
+ try {
41
+ const u = new URL(urlStr);
42
+ if (!ALLOWED_API_HOSTS.has(u.hostname)) {
43
+ throw new Error(`Blocked: API host '${u.hostname}' is not in the allowlist`);
44
+ }
45
+ return urlStr;
46
+ } catch (e) {
47
+ if (e.message.startsWith("Blocked:")) throw e;
48
+ throw new Error(`Invalid API base URL: ${urlStr}`);
49
+ }
50
+ }
51
+
52
+ // Validate at load time so a misconfigured env var fails fast.
53
+ validateApiBase(DEFAULT_API_BASE);
28
54
  /** Default network timeout in ms (override via opts.fetchTimeout or SIGRANK_FETCH_TIMEOUT). */
29
55
  export const DEFAULT_FETCH_TIMEOUT =
30
56
  Number(process.env.SIGRANK_FETCH_TIMEOUT) || 10_000;
@@ -16,9 +16,8 @@ export const TOOL_DEF = {
16
16
  "Ranks a paste of token counts locally and shows the cascade result (yield, leverage, velocity, class, card). This is a PREVIEW-ONLY tool — it does not publish to the board. The board's /api/v1/ingest-paste endpoint now requires an authenticated Supabase session, which MCP tools do not carry. To publish to the leaderboard, use submit_verified (which signs and posts to /api/v1/snapshots via the enrolled-device path) or submit directly through the signalaf.com web UI. Use this when you have token counts from ccusage or a dashboard and want to see your score instantly. Do NOT use this if you want to pull your local usage automatically — use tokenpull_submit for the zero-paste flow. Do NOT use this for multi-window dashboard pastes — use rank_windows to rank them first.",
17
17
  annotations: {
18
18
  title: "Preview paste ranking",
19
- ...ANNOTATIONS.destructiveHint,
19
+ ...ANNOTATIONS.readOnlyHint,
20
20
  ...ANNOTATIONS.idempotentHint,
21
- ...ANNOTATIONS.openWorldHint,
22
21
  },
23
22
  inputSchema: {
24
23
  type: "object",
@@ -16,9 +16,8 @@ export const TOOL_DEF = {
16
16
  "Pull your LOCAL token usage from session logs and compute the cascade per window — the zero-paste preview flow. Reads the four canonical pillars (input, output, cacheCreate, cacheRead) per window from your local logs and computes yield, leverage, velocity, class, and card. This is a PREVIEW-ONLY tool — it does not publish to the board. The board's /api/v1/ingest-paste endpoint now requires an authenticated Supabase session, which MCP tools do not carry. To publish to the leaderboard, use submit_verified (which signs and posts to /api/v1/snapshots via the enrolled-device path) or submit directly through the signalaf.com web UI. Token-only — no prompt content is read or transmitted.",
17
17
  annotations: {
18
18
  title: "Pull and preview tokens",
19
- ...ANNOTATIONS.destructiveHint,
19
+ ...ANNOTATIONS.readOnlyHint,
20
20
  ...ANNOTATIONS.idempotentHint,
21
- ...ANNOTATIONS.openWorldHint,
22
21
  },
23
22
  inputSchema: {
24
23
  type: "object",