lurqrun 0.1.7 → 0.1.9
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/README.md +312 -148
- package/dist/{auditHandler-JCOJSUYW.js → auditHandler-G7PHKMZR.js} +12 -11
- package/dist/autopilotInit-JO2SH5K3.js +266 -0
- package/dist/bin/lurq.js +238 -83
- package/dist/{browserAuth-B6G27USY.js → browserAuth-PVYODBNR.js} +4 -3
- package/dist/{cache-DKI34SVS.js → cache-ND4VOUVY.js} +2 -2
- package/dist/check-A3FJE62G.js +2613 -0
- package/dist/{check-2FDGUOV7.js → check-PQSQ2MMA.js} +1 -1
- package/dist/checkUpgrade-Q4CV7GXG.js +24 -0
- package/dist/{chunk-BCANRN5B.js → chunk-2GAYNIHG.js} +8 -1
- package/dist/chunk-2LXYRDUN.js +92 -0
- package/dist/chunk-2XMD4H2I.js +243 -0
- package/dist/chunk-3D2MPGOQ.js +181 -0
- package/dist/chunk-53SG6XWA.js +141 -0
- package/dist/chunk-5ABNDB3I.js +37 -0
- package/dist/chunk-5ALIJFDA.js +114 -0
- package/dist/{chunk-LYMPYETA.js → chunk-6353IJJ5.js} +270 -6
- package/dist/{chunk-M6NYEXCW.js → chunk-64DPQSXV.js} +1 -1
- package/dist/chunk-64YOP5BQ.js +320 -0
- package/dist/{chunk-2VMOWSRY.js → chunk-6DM6UQFD.js} +19 -1
- package/dist/{chunk-NH5I4KHH.js → chunk-75LMEMJ3.js} +1 -5
- package/dist/{chunk-FW6BD2NO.js → chunk-ABH4BTK4.js} +458 -121
- package/dist/chunk-AHRDDKNO.js +90 -0
- package/dist/chunk-AQ6IVSFB.js +119 -0
- package/dist/chunk-BM3LF5T6.js +132 -0
- package/dist/chunk-D3K6IZVR.js +12845 -0
- package/dist/chunk-DONTW3NE.js +171 -0
- package/dist/{chunk-UDVNA7EA.js → chunk-ETY4FSOW.js} +161 -8
- package/dist/{chunk-VL2E5T2A.js → chunk-FHRT32JH.js} +6 -3
- package/dist/{chunk-DWAGCNEL.js → chunk-GM5Y555O.js} +36 -103
- package/dist/{chunk-6L3U7DZ5.js → chunk-GNNGXVCG.js} +1 -1
- package/dist/{chunk-PSX3GIAN.js → chunk-HWFX4BC4.js} +2 -1
- package/dist/{checkUpgrade-F2WESBPM.js → chunk-ILKYIVYV.js} +72 -10
- package/dist/{chunk-HWBBVLOT.js → chunk-J3NUERU7.js} +1 -1
- package/dist/chunk-J3U2CPSK.js +136 -0
- package/dist/{chunk-Y5GI7RL3.js → chunk-J6XQ7OPZ.js} +9 -1
- package/dist/{chunk-3N3Q3DSW.js → chunk-JGIJZJ3X.js} +8 -8
- package/dist/{chunk-DB2VF5UD.js → chunk-JJCQVOC6.js} +16 -11
- package/dist/{chunk-LBFGSSF2.js → chunk-KMV4Y6R3.js} +2 -1
- package/dist/{chunk-L6N4JFW2.js → chunk-KP5ZDDPE.js} +81 -4
- package/dist/{chunk-CW5HJ3LX.js → chunk-KT7PWDNV.js} +1 -1
- package/dist/{chunk-SJOVFF7B.js → chunk-KYKSZ3XZ.js} +3 -2
- package/dist/{chunk-GPTKSNR6.js → chunk-L3V7AVM6.js} +2 -1
- package/dist/{chunk-CUP36ND3.js → chunk-M2CYYBAH.js} +145 -36
- package/dist/{chunk-IQ4SDKKY.js → chunk-N2NYPTRU.js} +31 -228
- package/dist/chunk-N4TJO44E.js +603 -0
- package/dist/chunk-NEZNAPPN.js +41 -0
- package/dist/{chunk-WQ23REYT.js → chunk-NGMJQBOV.js} +1 -1
- package/dist/{chunk-BULZAX2U.js → chunk-POHTPT37.js} +55 -38
- package/dist/{chunk-EA3DP5HG.js → chunk-PZZU3FQY.js} +155 -25
- package/dist/{chunk-4F7ZESPO.js → chunk-Q7CMOU5C.js} +3 -5
- package/dist/{chunk-LRD4GBYE.js → chunk-QUIMQ7YL.js} +1 -1
- package/dist/chunk-RG3YLU6E.js +49 -0
- package/dist/{chunk-4ZYCIMY4.js → chunk-SFY5MPJE.js} +25 -4
- package/dist/{chunk-ST2X2GYN.js → chunk-SHZFOSXC.js} +109 -20
- package/dist/{chunk-CIDWNUAP.js → chunk-SOXFMMXC.js} +8 -2
- package/dist/{chunk-B43LCXBM.js → chunk-SWMWVK2R.js} +81 -16
- package/dist/{chunk-J5FZYN4A.js → chunk-TVOCVIM7.js} +1 -1
- package/dist/{chunk-U5AT3TD4.js → chunk-X4W64MHU.js} +1735 -1858
- package/dist/{chunk-BV32UNLL.js → chunk-XA2SLNBR.js} +2 -2
- package/dist/{chunk-AHBP533R.js → chunk-XBTYJQEK.js} +7 -5
- package/dist/chunk-XGOV6KV4.js +413 -0
- package/dist/{chunk-OQS4GUSI.js → chunk-XIFQIFSZ.js} +210 -661
- package/dist/{chunk-XBIDMHSK.js → chunk-XLXPVN3Y.js} +2 -34
- package/dist/{chunk-LO35HLQZ.js → chunk-ZJ5XHA77.js} +25 -4
- package/dist/{client-IRKAMDYZ.js → client-SJIWK4CK.js} +3 -3
- package/dist/{commands-FIL5ET6P.js → commands-6BBLN5N5.js} +145 -33
- package/dist/{compat-R3UTFQ5Q.js → compat-6B3CRT5F.js} +6 -6
- package/dist/constants-HX3RTD6Q.js +24 -0
- package/dist/{dashboardIssue-WYYMBFIB.js → dashboardIssue-KBKLQMGC.js} +105 -23
- package/dist/{diff-GZA2774U.js → diff-I4SNUHU3.js} +1 -1
- package/dist/domains-RKRPVP5A.js +14 -0
- package/dist/env-UN6KGZ7S.js +15 -0
- package/dist/envCheck-IL22OTSC.js +71 -0
- package/dist/{extract-NKGKLIVT.js → extract-6WG265BL.js} +14 -3
- package/dist/{fetch-QYTUJVG2.js → fetch-GHIP3VHN.js} +4 -4
- package/dist/{firstTouch-QQTJH4QX.js → firstTouch-M64T2MWF.js} +1 -1
- package/dist/fix-Z7ZY55HB.js +220 -0
- package/dist/{handlers-GEJAVZDK.js → handlers-GOXW2GWZ.js} +19 -17
- package/dist/hook-TWFLIDK3.js +412 -0
- package/dist/{http-ETPYMBGD.js → http-7VF2RE2D.js} +2097 -509
- package/dist/{ingestQueue-VKN4KBIF.js → ingestQueue-RSEPMORK.js} +14 -12
- package/dist/{install-EK3W2COX.js → install-55EPX34C.js} +6 -6
- package/dist/{installSkill-VQJWJVCL.js → installSkill-A7KKPDMS.js} +21 -3
- package/dist/manifest-ENMIC54B.js +13 -0
- package/dist/{mcp-3JHD5SUZ.js → mcp-CM6CDLHM.js} +60 -32
- package/dist/mcpConfig-FENV6NI7.js +80 -0
- package/dist/{mcpHandlers-QFN4MCFL.js → mcpHandlers-2UCLKMWN.js} +7 -7
- package/dist/{mcpScan-QZHWENIP.js → mcpScan-CKBQNK5H.js} +306 -442
- package/dist/{mcpScanWorkflow-JPYCBGC4.js → mcpScanWorkflow-NFUD3S7U.js} +29 -12
- package/dist/{mcpStack-BYJCZNIV.js → mcpStack-FLQ6XY2P.js} +1 -1
- package/dist/model-ASMZWLM7.js +214 -0
- package/dist/{packages-THVFMWFP.js → packages-2XRHNBJ7.js} +3 -5
- package/dist/{plan-V4OEI3J4.js → plan-XRZS6C7Z.js} +23 -21
- package/dist/{planView-JRXGCG2N.js → planView-ZAKRTGVS.js} +4 -1
- package/dist/{policy-3P6BGRDN.js → policy-EQT43P7S.js} +5 -5
- package/dist/probe-ZEZFNIQZ.js +610 -0
- package/dist/publicUpgrades-JZEOV24A.js +42 -0
- package/dist/{references-6N7VEPHT.js → references-I6Y4BSRR.js} +3 -1
- package/dist/{release-4U4ABNSJ.js → release-EUOM5I3R.js} +5 -5
- package/dist/{remote-YGCXYI4V.js → remote-I5O43WAY.js} +13 -3
- package/dist/rename-OS6JYBZQ.js +204 -0
- package/dist/{reportRuns-CKQQYLY4.js → reportRuns-O4X7ZFTX.js} +15 -2
- package/dist/safeFetch-COERXGFN.js +19 -0
- package/dist/{sandbox-MEZLAODF.js → sandbox-46TZNYZT.js} +4 -4
- package/dist/sarif-WLVJFJ7U.js +125 -0
- package/dist/server-LROMHS62.js +59 -0
- package/dist/{surface-YL6O67W3.js → surface-CZMHQLV3.js} +5 -3
- package/dist/{surface-V62GE554.js → surface-OH4TZR32.js} +18 -16
- package/dist/{surfaceHandlers-X2IZKA3E.js → surfaceHandlers-BDYRZMAC.js} +5 -5
- package/dist/{typecheck-X7U5ELMR.js → typecheck-NGOKNAJY.js} +23 -9
- package/dist/{uninstall-P7RGBX6G.js → uninstall-4E5YUDQO.js} +30 -4
- package/dist/{upgrade-NQ5IWFZB.js → upgrade-S72W7JVC.js} +86 -32
- package/dist/{upgradePlan-A4LRKLEG.js → upgradePlan-F3OUNL3E.js} +46 -11
- package/dist/upkeepHandler-7Q56A4UA.js +13 -0
- package/dist/{userConfig-Z3GQE776.js → userConfig-ICASHI47.js} +1 -1
- package/dist/{watch-DGFMWUDL.js → watch-LZPOKWCL.js} +24 -34
- package/package.json +3 -2
- package/templates/skill-instructions.md +22 -3
- package/dist/chunk-6AAEVQ7I.js +0 -6336
- package/dist/chunk-I2JUKN6Z.js +0 -24
- package/dist/server-KFUD5X57.js +0 -55
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
SseError,
|
|
4
|
+
StreamableHTTPError,
|
|
5
|
+
UnauthorizedError
|
|
6
|
+
} from "./chunk-X4W64MHU.js";
|
|
7
|
+
import {
|
|
8
|
+
ErrorCode,
|
|
9
|
+
McpError
|
|
10
|
+
} from "./chunk-D3K6IZVR.js";
|
|
11
|
+
import {
|
|
12
|
+
init_esm_shims
|
|
13
|
+
} from "./chunk-I3M2KJXB.js";
|
|
14
|
+
|
|
15
|
+
// src/mcpScan/errors.ts
|
|
16
|
+
init_esm_shims();
|
|
17
|
+
var ENV_COMPLAINT = /\b([A-Z][A-Z0-9]{2,}(?:_[A-Z0-9]+)+)\b[^.\n]{0,60}?\b(required|must be set|not set|missing|is not defined)\b|\b(required|must be set|missing)\b[^.\n]{0,60}?\b([A-Z][A-Z0-9]{2,}(?:_[A-Z0-9]+)+)\b/;
|
|
18
|
+
function sniffMissingEnv(text) {
|
|
19
|
+
const m = ENV_COMPLAINT.exec(text);
|
|
20
|
+
return m ? m[1] ?? m[4] ?? null : null;
|
|
21
|
+
}
|
|
22
|
+
var NETWORK_CODES = /* @__PURE__ */ new Set([
|
|
23
|
+
"ECONNREFUSED",
|
|
24
|
+
"ENOTFOUND",
|
|
25
|
+
"EAI_AGAIN",
|
|
26
|
+
"ECONNRESET",
|
|
27
|
+
"ETIMEDOUT",
|
|
28
|
+
"EHOSTUNREACH",
|
|
29
|
+
"ENETUNREACH",
|
|
30
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
31
|
+
"UND_ERR_SOCKET",
|
|
32
|
+
"CERT_HAS_EXPIRED",
|
|
33
|
+
"DEPTH_ZERO_SELF_SIGNED_CERT",
|
|
34
|
+
"SELF_SIGNED_CERT_IN_CHAIN",
|
|
35
|
+
"UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|
36
|
+
"ERR_TLS_CERT_ALTNAME_INVALID"
|
|
37
|
+
]);
|
|
38
|
+
function causeCode(err) {
|
|
39
|
+
let cur = err;
|
|
40
|
+
for (let i = 0; i < 5 && cur; i++) {
|
|
41
|
+
const code = cur.code;
|
|
42
|
+
if (typeof code === "string") return code;
|
|
43
|
+
cur = cur.cause;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
var msg = (err) => err instanceof Error ? err.message : String(err);
|
|
48
|
+
function classifyError(err, ctx) {
|
|
49
|
+
const message = msg(err).slice(0, 500);
|
|
50
|
+
if (err instanceof UnauthorizedError) {
|
|
51
|
+
return {
|
|
52
|
+
status: "auth_required",
|
|
53
|
+
error: message || "the server requires authorization",
|
|
54
|
+
hint: "this server signs in with OAuth, and lurq cannot reuse the token your agent holds; ask your agent to pass its tool list to the mcp_stack tool instead"
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const httpCode = err instanceof StreamableHTTPError || err instanceof SseError ? err.code : void 0;
|
|
58
|
+
if (httpCode === 401 || httpCode === 403) {
|
|
59
|
+
return {
|
|
60
|
+
status: "auth_required",
|
|
61
|
+
error: `HTTP ${httpCode}`,
|
|
62
|
+
hint: "the server rejected the credentials in this config; check the Authorization header or token it is given"
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (typeof httpCode === "number" && httpCode > 0) {
|
|
66
|
+
return {
|
|
67
|
+
status: "unreachable",
|
|
68
|
+
error: `HTTP ${httpCode}: ${message}`,
|
|
69
|
+
hint: httpCode === 404 ? "nothing answers MCP at this url; check the path" : null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (err instanceof McpError && err.code === ErrorCode.RequestTimeout) {
|
|
73
|
+
return {
|
|
74
|
+
status: "timeout",
|
|
75
|
+
error: message,
|
|
76
|
+
hint: ctx.transport === "stdio" ? "the server did not answer in time; a first run of npx/uvx downloads the package, so try again with a longer --timeout" : null
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const code = causeCode(err);
|
|
80
|
+
if (code === "ENOENT" && ctx.transport === "stdio") {
|
|
81
|
+
return {
|
|
82
|
+
status: "spawn_failed",
|
|
83
|
+
error: `command not found: ${ctx.command ?? "(none)"}`,
|
|
84
|
+
hint: "install it, or use an absolute path in the config"
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (code && NETWORK_CODES.has(code)) {
|
|
88
|
+
return { status: "unreachable", error: `${code}: ${message}`, hint: null };
|
|
89
|
+
}
|
|
90
|
+
if (err instanceof TypeError && /fetch failed/i.test(message)) {
|
|
91
|
+
const cause = err.cause;
|
|
92
|
+
return {
|
|
93
|
+
status: "unreachable",
|
|
94
|
+
error: cause ? `fetch failed: ${msg(cause).slice(0, 300)}` : message,
|
|
95
|
+
hint: null
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const closed = err instanceof McpError && err.code === ErrorCode.ConnectionClosed || /connection closed/i.test(message);
|
|
99
|
+
if (closed && ctx.transport === "stdio") {
|
|
100
|
+
const missing = sniffMissingEnv(ctx.stderrTail);
|
|
101
|
+
if (missing) {
|
|
102
|
+
return {
|
|
103
|
+
status: "needs_config",
|
|
104
|
+
error: `the server exited, and its output names ${missing} as required`,
|
|
105
|
+
hint: `set ${missing} in this server's env block`
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (ctx.stdoutNoise > 0 && !ctx.stderrTail.trim()) {
|
|
109
|
+
return {
|
|
110
|
+
status: "protocol_error",
|
|
111
|
+
error: "the server wrote non-protocol output to stdout and then closed",
|
|
112
|
+
hint: "stdio servers must log to stderr; stdout is reserved for JSON-RPC"
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
status: "spawn_failed",
|
|
117
|
+
error: ctx.stderrTail.trim() ? `exited before completing the handshake: ${ctx.stderrTail.trim().split("\n").slice(-3).join(" | ")}` : "exited before completing the handshake",
|
|
118
|
+
hint: null
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (/protocol version is not supported/i.test(message)) {
|
|
122
|
+
return {
|
|
123
|
+
status: "protocol_error",
|
|
124
|
+
error: message,
|
|
125
|
+
hint: "the server speaks a protocol revision this lurq version does not; upgrade lurq"
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (ctx.stdoutNoise > 0) {
|
|
129
|
+
return {
|
|
130
|
+
status: "protocol_error",
|
|
131
|
+
error: `${message} (the server also wrote ${ctx.stdoutNoise} non-protocol line(s) to stdout)`,
|
|
132
|
+
hint: "stdio servers must log to stderr; stdout is reserved for JSON-RPC"
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return { status: "protocol_error", error: message || "unknown error", hint: null };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export {
|
|
139
|
+
sniffMissingEnv,
|
|
140
|
+
classifyError
|
|
141
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-I3M2KJXB.js";
|
|
5
|
+
|
|
6
|
+
// src/remoteProbe/url.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
var PLACEHOLDER = /\{[^{}]+\}/;
|
|
9
|
+
function endpointIdentity(raw) {
|
|
10
|
+
if (typeof raw !== "string") return null;
|
|
11
|
+
const trimmed = raw.trim();
|
|
12
|
+
if (!trimmed || trimmed.length > 2048) return null;
|
|
13
|
+
const templated = PLACEHOLDER.test(trimmed);
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = new URL(templated ? trimmed.replace(/\{[^{}]+\}/g, "placeholder") : trimmed);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
|
|
21
|
+
const host = parsed.hostname.toLowerCase();
|
|
22
|
+
if (!host) return null;
|
|
23
|
+
if (templated) return { url: trimmed, host, templated: true };
|
|
24
|
+
parsed.hash = "";
|
|
25
|
+
const path = parsed.pathname === "/" ? "" : parsed.pathname;
|
|
26
|
+
const port = parsed.port ? `:${parsed.port}` : "";
|
|
27
|
+
const auth = parsed.username ? `${parsed.username}${parsed.password ? `:${parsed.password}` : ""}@` : "";
|
|
28
|
+
return {
|
|
29
|
+
url: `${parsed.protocol}//${auth}${host}${port}${path}${parsed.search}`,
|
|
30
|
+
host,
|
|
31
|
+
templated: false
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
endpointIdentity
|
|
37
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
require_semver
|
|
4
|
+
} from "./chunk-3GHJR7XR.js";
|
|
5
|
+
import {
|
|
6
|
+
__toESM,
|
|
7
|
+
init_esm_shims
|
|
8
|
+
} from "./chunk-I3M2KJXB.js";
|
|
9
|
+
|
|
10
|
+
// src/fix/manifest.ts
|
|
11
|
+
init_esm_shims();
|
|
12
|
+
var import_semver = __toESM(require_semver(), 1);
|
|
13
|
+
import { readFileSync } from "fs";
|
|
14
|
+
import { join } from "path";
|
|
15
|
+
import ts from "typescript";
|
|
16
|
+
var BLOCKS = ["dependencies", "devDependencies", "optionalDependencies"];
|
|
17
|
+
var SIMPLE_RANGE = /^(\^|~)?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/;
|
|
18
|
+
function declaredRange(text, pkg) {
|
|
19
|
+
const sf = ts.parseJsonText("package.json", text);
|
|
20
|
+
const root = sf.statements[0]?.expression;
|
|
21
|
+
if (!root || !ts.isObjectLiteralExpression(root)) return null;
|
|
22
|
+
const propNamed = (obj, name) => obj.properties.find(
|
|
23
|
+
(p) => ts.isPropertyAssignment(p) && ts.isStringLiteral(p.name) && p.name.text === name
|
|
24
|
+
);
|
|
25
|
+
for (const block of BLOCKS) {
|
|
26
|
+
const blockProp = propNamed(root, block);
|
|
27
|
+
if (!blockProp || !ts.isObjectLiteralExpression(blockProp.initializer)) continue;
|
|
28
|
+
const dep = propNamed(blockProp.initializer, pkg);
|
|
29
|
+
if (!dep || !ts.isStringLiteral(dep.initializer)) continue;
|
|
30
|
+
const node = dep.initializer;
|
|
31
|
+
return { block, range: node.text, start: node.getStart(sf) + 1, end: node.getEnd() - 1 };
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function decideRange(file, found, toVersion) {
|
|
36
|
+
if (!import_semver.default.valid(toVersion)) {
|
|
37
|
+
return { refusedBecause: `${toVersion} is not an exact version` };
|
|
38
|
+
}
|
|
39
|
+
if (import_semver.default.validRange(found.range) && import_semver.default.satisfies(toVersion, found.range)) {
|
|
40
|
+
return { satisfied: true };
|
|
41
|
+
}
|
|
42
|
+
const simple = SIMPLE_RANGE.exec(found.range);
|
|
43
|
+
if (!simple) {
|
|
44
|
+
return {
|
|
45
|
+
refusedBecause: `"${found.range}" is not a plain ^, ~ or exact range, so what it should become is a judgement`
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const prefix = simple[1] ?? "";
|
|
49
|
+
return {
|
|
50
|
+
edit: {
|
|
51
|
+
file,
|
|
52
|
+
start: found.start,
|
|
53
|
+
end: found.end,
|
|
54
|
+
text: `${prefix}${toVersion}`,
|
|
55
|
+
was: found.range
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function manifestFindings(root, targets, opts = {}) {
|
|
60
|
+
const files = opts.files ?? ["package.json"];
|
|
61
|
+
const read = opts.read ?? ((file) => {
|
|
62
|
+
try {
|
|
63
|
+
return readFileSync(join(root, file), "utf8");
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const texts = /* @__PURE__ */ new Map();
|
|
69
|
+
for (const file of files) {
|
|
70
|
+
const text = read(file);
|
|
71
|
+
if (text !== null) texts.set(file, text);
|
|
72
|
+
}
|
|
73
|
+
const findings = [];
|
|
74
|
+
const refused = [];
|
|
75
|
+
for (const target of targets) {
|
|
76
|
+
const edits = [];
|
|
77
|
+
const bumped = [];
|
|
78
|
+
for (const [file, text] of texts) {
|
|
79
|
+
const found = declaredRange(text, target.package);
|
|
80
|
+
if (!found) continue;
|
|
81
|
+
const decision = decideRange(file, found, target.toVersion);
|
|
82
|
+
if (decision.edit) {
|
|
83
|
+
edits.push(decision.edit);
|
|
84
|
+
bumped.push(file);
|
|
85
|
+
} else if (decision.refusedBecause) {
|
|
86
|
+
refused.push({ package: target.package, file, reason: decision.refusedBecause });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (edits.length === 0) continue;
|
|
90
|
+
findings.push({
|
|
91
|
+
domain: "package",
|
|
92
|
+
code: `outdated-range:${target.package}`,
|
|
93
|
+
// Blocking: with the source rewritten and the range still pinning the old
|
|
94
|
+
// major, the next install puts the old version back under new code.
|
|
95
|
+
severity: "blocking",
|
|
96
|
+
detail: `${target.package} is declared at a range that excludes ${target.toVersion} in ${bumped.length} manifest(s): ${bumped.join(", ")}`,
|
|
97
|
+
file: bumped[0],
|
|
98
|
+
evidence: `upgrading ${target.package} ${target.fromVersion} \u2192 ${target.toVersion}`,
|
|
99
|
+
fix: {
|
|
100
|
+
summary: `bump ${target.package} to ${target.toVersion} in ${bumped.length} manifest(s)`,
|
|
101
|
+
edits,
|
|
102
|
+
// Installing is the user's call; the type check is what proves the tree agrees.
|
|
103
|
+
verify: ["typecheck"]
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return { findings, refused };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
declaredRange,
|
|
112
|
+
decideRange,
|
|
113
|
+
manifestFindings
|
|
114
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
EMBEDDING_DIM
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-L3V7AVM6.js";
|
|
5
5
|
import {
|
|
6
6
|
__export,
|
|
7
7
|
init_esm_shims
|
|
@@ -14,6 +14,7 @@ __export(schema_exports, {
|
|
|
14
14
|
apiKeys: () => apiKeys,
|
|
15
15
|
apiSurfaces: () => apiSurfaces,
|
|
16
16
|
askSpendDaily: () => askSpendDaily,
|
|
17
|
+
builderScans: () => builderScans,
|
|
17
18
|
claims: () => claims,
|
|
18
19
|
compatEdges: () => compatEdges,
|
|
19
20
|
compatVerifyQueue: () => compatVerifyQueue,
|
|
@@ -23,8 +24,15 @@ __export(schema_exports, {
|
|
|
23
24
|
mcpChangeEvents: () => mcpChangeEvents,
|
|
24
25
|
mcpContracts: () => mcpContracts,
|
|
25
26
|
mcpDeployments: () => mcpDeployments,
|
|
27
|
+
mcpEndpointChangeAcks: () => mcpEndpointChangeAcks,
|
|
28
|
+
mcpEndpointChanges: () => mcpEndpointChanges,
|
|
29
|
+
mcpEndpointObservations: () => mcpEndpointObservations,
|
|
30
|
+
mcpEndpointServers: () => mcpEndpointServers,
|
|
26
31
|
mcpObservations: () => mcpObservations,
|
|
32
|
+
mcpPins: () => mcpPins,
|
|
27
33
|
mcpPublicReports: () => mcpPublicReports,
|
|
34
|
+
mcpRegistryServers: () => mcpRegistryServers,
|
|
35
|
+
mcpRemoteEndpoints: () => mcpRemoteEndpoints,
|
|
28
36
|
notificationChannels: () => notificationChannels,
|
|
29
37
|
notificationDeliveries: () => notificationDeliveries,
|
|
30
38
|
notificationItems: () => notificationItems,
|
|
@@ -36,6 +44,7 @@ __export(schema_exports, {
|
|
|
36
44
|
policyDecisions: () => policyDecisions,
|
|
37
45
|
recommendationOutcomes: () => recommendationOutcomes,
|
|
38
46
|
repoAlerts: () => repoAlerts,
|
|
47
|
+
repoPolicyDefaults: () => repoPolicyDefaults,
|
|
39
48
|
repos: () => repos,
|
|
40
49
|
resolvedClosures: () => resolvedClosures,
|
|
41
50
|
seedPackages: () => seedPackages,
|
|
@@ -161,7 +170,17 @@ var packages = pgTable(
|
|
|
161
170
|
* Null for crawler/_changes-created packages, or ones ingested before
|
|
162
171
|
* dashboard accounts existed. Stamped once via a standalone WHERE ... IS NULL
|
|
163
172
|
* update kept out of upsertPackage, so re-syncs can never clobber it. */
|
|
164
|
-
firstRequestedByOwnerId: text("first_requested_by_owner_id")
|
|
173
|
+
firstRequestedByOwnerId: text("first_requested_by_owner_id"),
|
|
174
|
+
/**
|
|
175
|
+
* Failed API-surface extractions for `surface_attempted_version`. The worker
|
|
176
|
+
* stops asking once a version has failed SURFACE_MAX_ATTEMPTS times; a new
|
|
177
|
+
* latest version starts the count again, since it may ship types the last
|
|
178
|
+
* one did not. Without this, a package with no extractable surface was
|
|
179
|
+
* re-attempted at random every hour, forever. Not in upsertPackage's row,
|
|
180
|
+
* so re-syncs never reset it.
|
|
181
|
+
*/
|
|
182
|
+
surfaceAttempts: integer("surface_attempts").notNull().default(0),
|
|
183
|
+
surfaceAttemptedVersion: text("surface_attempted_version")
|
|
165
184
|
},
|
|
166
185
|
(table) => [
|
|
167
186
|
uniqueIndex("packages_ecosystem_name_idx").on(table.ecosystem, table.name),
|
|
@@ -211,6 +230,13 @@ var discoveryQueue = pgTable(
|
|
|
211
230
|
* and never reaching the write that would take it off the queue. Same
|
|
212
231
|
* treatment `compat_verify_queue.attempts` already gives a failing set. */
|
|
213
232
|
attempts: integer("attempts").notNull().default(0),
|
|
233
|
+
/**
|
|
234
|
+
* The account whose query asked for this package (`reactive` rows only),
|
|
235
|
+
* credited as first requester when it is ingested. Stored here because the
|
|
236
|
+
* on-demand ingest used to live only in the API process's memory, and a
|
|
237
|
+
* deploy mid-backlog dropped both the work and the attribution.
|
|
238
|
+
*/
|
|
239
|
+
requestedByOwnerId: text("requested_by_owner_id"),
|
|
214
240
|
discoveredAt: ts("discovered_at").notNull().defaultNow()
|
|
215
241
|
},
|
|
216
242
|
(table) => [index("discovery_queue_status_idx").on(table.status)]
|
|
@@ -392,6 +418,11 @@ var ownerUsageDaily = pgTable(
|
|
|
392
418
|
index("owner_usage_daily_owner_date_idx").on(table.ownerId, table.date)
|
|
393
419
|
]
|
|
394
420
|
);
|
|
421
|
+
var repoPolicyDefaults = pgTable("repo_policy_defaults", {
|
|
422
|
+
ownerId: text("owner_id").primaryKey(),
|
|
423
|
+
policy: jsonb("policy").$type().notNull(),
|
|
424
|
+
updatedAt: ts("updated_at").notNull().defaultNow()
|
|
425
|
+
});
|
|
395
426
|
var repos = pgTable(
|
|
396
427
|
"repos",
|
|
397
428
|
{
|
|
@@ -458,6 +489,21 @@ var upgradeRuns = pgTable(
|
|
|
458
489
|
* row per package+target and updates in place.
|
|
459
490
|
*/
|
|
460
491
|
runUrl: text("run_url").notNull().default(""),
|
|
492
|
+
/**
|
|
493
|
+
* What started the run, from GITHUB_EVENT_NAME. See `RunTrigger`.
|
|
494
|
+
*
|
|
495
|
+
* NULLABLE, and deliberately NOT in the dedup index below. Every row
|
|
496
|
+
* written before this column existed has no trigger, and back-filling them
|
|
497
|
+
* with 'schedule' would invent evidence the log then presents as fact — the
|
|
498
|
+
* same rule `unverified` and `analysedOnly` follow. The dashboard renders
|
|
499
|
+
* null as "not recorded".
|
|
500
|
+
*
|
|
501
|
+
* Keeping it out of the dedup key is not a style choice: `runUrl` is in
|
|
502
|
+
* that key and is NOT NULL precisely because Postgres treats NULLs as
|
|
503
|
+
* distinct, so a nullable column there would let every re-post insert a
|
|
504
|
+
* duplicate instead of updating in place.
|
|
505
|
+
*/
|
|
506
|
+
trigger: text("trigger").$type(),
|
|
461
507
|
createdAt: ts("created_at").notNull().defaultNow()
|
|
462
508
|
},
|
|
463
509
|
(table) => [
|
|
@@ -480,7 +526,10 @@ var repoAlerts = pgTable(
|
|
|
480
526
|
id: serial("id").primaryKey(),
|
|
481
527
|
/** Clerk user id, copied from the repo — alerts are read owner-scoped. */
|
|
482
528
|
ownerId: text("owner_id").notNull(),
|
|
483
|
-
|
|
529
|
+
/** Null for an account that runs `check-upgrade` on a repo lurq has no
|
|
530
|
+
* GitHub App installation for: the alert is keyed by `repo_full_name` from
|
|
531
|
+
* its upgrade runs instead, and there is no repo page to link to. */
|
|
532
|
+
repoId: integer("repo_id"),
|
|
484
533
|
/** Denormalized so the feed renders without a join, as in `upgrade_runs`. */
|
|
485
534
|
repoFullName: text("repo_full_name").notNull(),
|
|
486
535
|
packageName: text("package_name").notNull(),
|
|
@@ -507,7 +556,11 @@ var repoAlerts = pgTable(
|
|
|
507
556
|
// One alert per repo per release. A re-sync of the same version — and the
|
|
508
557
|
// watcher re-syncs on every publish, including non-latest backports — must
|
|
509
558
|
// not re-notify.
|
|
510
|
-
uniqueIndex("repo_alerts_dedup_idx").on(table.repoId, table.packageName, table.toVersion)
|
|
559
|
+
uniqueIndex("repo_alerts_dedup_idx").on(table.repoId, table.packageName, table.toVersion),
|
|
560
|
+
// The same rule for alerts with no connected repo. Postgres treats NULLs as
|
|
561
|
+
// distinct, so the index above can never dedupe those rows; this one covers
|
|
562
|
+
// exactly them. Partial, so adding it cannot fail on existing rows.
|
|
563
|
+
uniqueIndex("repo_alerts_cli_dedup_idx").on(table.ownerId, table.repoFullName, table.packageName, table.toVersion).where(sql`repo_id is null`)
|
|
511
564
|
]
|
|
512
565
|
);
|
|
513
566
|
var surfaceQueue = pgTable(
|
|
@@ -532,6 +585,12 @@ var surfaceQueue = pgTable(
|
|
|
532
585
|
specKey: text("spec_key").notNull().unique(),
|
|
533
586
|
/** Failed drains bump this; the worker drops a spec that keeps failing. */
|
|
534
587
|
attempts: integer("attempts").notNull().default(0),
|
|
588
|
+
/**
|
|
589
|
+
* Not eligible before this. Set on every retry with an exponential delay, so
|
|
590
|
+
* a spec that just failed waits instead of being retried the next cycle and
|
|
591
|
+
* — oldest-first — blocking every newer spec behind it. Null = ready now.
|
|
592
|
+
*/
|
|
593
|
+
nextAttemptAt: ts("next_attempt_at"),
|
|
535
594
|
requestedAt: ts("requested_at").notNull().defaultNow()
|
|
536
595
|
},
|
|
537
596
|
(table) => [index("surface_queue_requested_idx").on(table.kind, table.requestedAt)]
|
|
@@ -801,7 +860,11 @@ var mcpDeployments = pgTable(
|
|
|
801
860
|
lastChangedAt: ts("last_changed_at")
|
|
802
861
|
},
|
|
803
862
|
(table) => [
|
|
804
|
-
uniqueIndex("mcp_deployments_identity_idx").on(
|
|
863
|
+
uniqueIndex("mcp_deployments_identity_idx").on(
|
|
864
|
+
table.ownerId,
|
|
865
|
+
table.serverKey,
|
|
866
|
+
table.configFingerprint
|
|
867
|
+
),
|
|
805
868
|
index("mcp_deployments_owner_idx").on(table.ownerId, table.lastScannedAt)
|
|
806
869
|
]
|
|
807
870
|
);
|
|
@@ -854,7 +917,9 @@ var mcpPublicReports = pgTable(
|
|
|
854
917
|
reportedAt: ts("reported_at").notNull().defaultNow()
|
|
855
918
|
},
|
|
856
919
|
(table) => [
|
|
857
|
-
primaryKey({
|
|
920
|
+
primaryKey({
|
|
921
|
+
columns: [table.registry, table.packageName, table.version, table.contentHash, table.ownerId]
|
|
922
|
+
}),
|
|
858
923
|
index("mcp_public_reports_version_idx").on(table.registry, table.packageName, table.version)
|
|
859
924
|
]
|
|
860
925
|
);
|
|
@@ -924,6 +989,196 @@ var notificationChannels = pgTable(
|
|
|
924
989
|
},
|
|
925
990
|
(table) => [index("notification_channels_owner_idx").on(table.ownerId)]
|
|
926
991
|
);
|
|
992
|
+
var builderScans = pgTable(
|
|
993
|
+
"builder_scans",
|
|
994
|
+
{
|
|
995
|
+
ownerId: text("owner_id").notNull(),
|
|
996
|
+
target: text("target").notNull(),
|
|
997
|
+
login: text("login").notNull(),
|
|
998
|
+
archetype: text("archetype").$type().notNull(),
|
|
999
|
+
avatarUrl: text("avatar_url").notNull(),
|
|
1000
|
+
// What builderStanding.ts ranks on, copied out of `profile` at save, so
|
|
1001
|
+
// ranking reads seven integers per builder instead of every whole report.
|
|
1002
|
+
repos: integer("repos").notNull(),
|
|
1003
|
+
active90: integer("active_90").notNull(),
|
|
1004
|
+
stars: integer("stars").notNull(),
|
|
1005
|
+
depsTracked: integer("deps_tracked").notNull(),
|
|
1006
|
+
depsBehind: integer("deps_behind").notNull(),
|
|
1007
|
+
depsMajor: integer("deps_major").notNull(),
|
|
1008
|
+
advisories: integer("advisories").notNull(),
|
|
1009
|
+
profile: jsonb("profile").$type().notNull(),
|
|
1010
|
+
scannedAt: ts("scanned_at").notNull().defaultNow(),
|
|
1011
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
1012
|
+
},
|
|
1013
|
+
(table) => [
|
|
1014
|
+
primaryKey({ columns: [table.ownerId, table.target] }),
|
|
1015
|
+
index("builder_scans_owner_recent_idx").on(table.ownerId, table.scannedAt)
|
|
1016
|
+
]
|
|
1017
|
+
);
|
|
1018
|
+
var mcpRegistryServers = pgTable(
|
|
1019
|
+
"mcp_registry_servers",
|
|
1020
|
+
{
|
|
1021
|
+
name: text("name").notNull(),
|
|
1022
|
+
version: text("version").notNull(),
|
|
1023
|
+
title: text("title"),
|
|
1024
|
+
description: text("description"),
|
|
1025
|
+
websiteUrl: text("website_url"),
|
|
1026
|
+
repositoryUrl: text("repository_url"),
|
|
1027
|
+
/** `active`, `deprecated`, `deleted`, … as the registry reports it. */
|
|
1028
|
+
status: text("status").notNull(),
|
|
1029
|
+
isLatest: boolean("is_latest").notNull(),
|
|
1030
|
+
remotes: jsonb("remotes").$type().notNull(),
|
|
1031
|
+
packages: jsonb("packages").$type().notNull(),
|
|
1032
|
+
publishedAt: ts("published_at"),
|
|
1033
|
+
registryUpdatedAt: ts("registry_updated_at"),
|
|
1034
|
+
syncedAt: ts("synced_at").notNull().defaultNow()
|
|
1035
|
+
},
|
|
1036
|
+
(table) => [
|
|
1037
|
+
primaryKey({ columns: [table.name, table.version] }),
|
|
1038
|
+
index("mcp_registry_servers_latest_idx").on(table.name).where(sql`${table.isLatest}`),
|
|
1039
|
+
index("mcp_registry_servers_updated_idx").on(table.registryUpdatedAt)
|
|
1040
|
+
]
|
|
1041
|
+
);
|
|
1042
|
+
var mcpRemoteEndpoints = pgTable(
|
|
1043
|
+
"mcp_remote_endpoints",
|
|
1044
|
+
{
|
|
1045
|
+
id: serial("id").primaryKey(),
|
|
1046
|
+
url: text("url").notNull().unique(),
|
|
1047
|
+
host: text("host").notNull(),
|
|
1048
|
+
/** Transport the registry declares: `streamable-http` or `sse`. */
|
|
1049
|
+
transport: text("transport").notNull(),
|
|
1050
|
+
/** URL carries `{placeholders}`: never probed, answered as setup-dependent. */
|
|
1051
|
+
templated: boolean("templated").notNull().default(false),
|
|
1052
|
+
/** A maintainer asked not to be probed. Never scheduled again. */
|
|
1053
|
+
optedOut: boolean("opted_out").notNull().default(false),
|
|
1054
|
+
lastStatus: text("last_status").$type(),
|
|
1055
|
+
lastHttpStatus: integer("last_http_status"),
|
|
1056
|
+
/** Content hash of the last contract read (a key into `mcp_contracts`). */
|
|
1057
|
+
lastContentHash: text("last_content_hash"),
|
|
1058
|
+
/** Hash of the auth profile, so an auth change is detectable without a diff. */
|
|
1059
|
+
lastAuthHash: text("last_auth_hash"),
|
|
1060
|
+
auth: jsonb("auth").$type(),
|
|
1061
|
+
violations: jsonb("violations").$type().notNull().default([]),
|
|
1062
|
+
protocolMode: text("protocol_mode").$type(),
|
|
1063
|
+
protocolVersion: text("protocol_version"),
|
|
1064
|
+
serverName: text("server_name"),
|
|
1065
|
+
serverVersion: text("server_version"),
|
|
1066
|
+
finalUrl: text("final_url"),
|
|
1067
|
+
latencyMs: integer("latency_ms"),
|
|
1068
|
+
lastError: text("last_error"),
|
|
1069
|
+
consecutiveFailures: integer("consecutive_failures").notNull().default(0),
|
|
1070
|
+
probeCount: integer("probe_count").notNull().default(0),
|
|
1071
|
+
firstSeenAt: ts("first_seen_at").notNull().defaultNow(),
|
|
1072
|
+
lastProbedAt: ts("last_probed_at"),
|
|
1073
|
+
lastChangedAt: ts("last_changed_at"),
|
|
1074
|
+
nextProbeAt: ts("next_probe_at").notNull().defaultNow(),
|
|
1075
|
+
leaseUntil: ts("lease_until"),
|
|
1076
|
+
/** No live registry entry names this URL any more. Kept for history. */
|
|
1077
|
+
removedAt: ts("removed_at"),
|
|
1078
|
+
/**
|
|
1079
|
+
* The key an account's own `lurq mcp-scan` gives this server (`remote:<host><path>`,
|
|
1080
|
+
* query dropped). Joining on it is how a change the public probe sees reaches
|
|
1081
|
+
* every account already running the server, without anyone rescanning.
|
|
1082
|
+
*/
|
|
1083
|
+
scanKey: text("scan_key")
|
|
1084
|
+
},
|
|
1085
|
+
(table) => [
|
|
1086
|
+
index("mcp_remote_endpoints_scan_key_idx").on(table.scanKey),
|
|
1087
|
+
index("mcp_remote_endpoints_due_idx").on(table.nextProbeAt).where(
|
|
1088
|
+
sql`${table.optedOut} = false and ${table.templated} = false and ${table.removedAt} is null`
|
|
1089
|
+
),
|
|
1090
|
+
index("mcp_remote_endpoints_host_idx").on(table.host)
|
|
1091
|
+
]
|
|
1092
|
+
);
|
|
1093
|
+
var mcpEndpointServers = pgTable(
|
|
1094
|
+
"mcp_endpoint_servers",
|
|
1095
|
+
{
|
|
1096
|
+
endpointId: integer("endpoint_id").notNull().references(() => mcpRemoteEndpoints.id),
|
|
1097
|
+
serverName: text("server_name").notNull(),
|
|
1098
|
+
headers: jsonb("headers").$type().notNull().default([]),
|
|
1099
|
+
lastSeenAt: ts("last_seen_at").notNull().defaultNow(),
|
|
1100
|
+
/**
|
|
1101
|
+
* The server's latest registry version stopped naming this URL, or the
|
|
1102
|
+
* server was deleted. Marked, never deleted: rows in this schema are history.
|
|
1103
|
+
*/
|
|
1104
|
+
removedAt: ts("removed_at")
|
|
1105
|
+
},
|
|
1106
|
+
(table) => [
|
|
1107
|
+
primaryKey({ columns: [table.endpointId, table.serverName] }),
|
|
1108
|
+
index("mcp_endpoint_servers_name_idx").on(table.serverName)
|
|
1109
|
+
]
|
|
1110
|
+
);
|
|
1111
|
+
var mcpEndpointObservations = pgTable(
|
|
1112
|
+
"mcp_endpoint_observations",
|
|
1113
|
+
{
|
|
1114
|
+
id: serial("id").primaryKey(),
|
|
1115
|
+
endpointId: integer("endpoint_id").notNull().references(() => mcpRemoteEndpoints.id),
|
|
1116
|
+
status: text("status").$type().notNull(),
|
|
1117
|
+
httpStatus: integer("http_status"),
|
|
1118
|
+
contentHash: text("content_hash"),
|
|
1119
|
+
authHash: text("auth_hash"),
|
|
1120
|
+
violations: jsonb("violations").$type().notNull().default([]),
|
|
1121
|
+
protocolVersion: text("protocol_version"),
|
|
1122
|
+
error: text("error"),
|
|
1123
|
+
probeCount: integer("probe_count").notNull().default(1),
|
|
1124
|
+
firstSeenAt: ts("first_seen_at").notNull().defaultNow(),
|
|
1125
|
+
lastSeenAt: ts("last_seen_at").notNull().defaultNow()
|
|
1126
|
+
},
|
|
1127
|
+
(table) => [
|
|
1128
|
+
index("mcp_endpoint_observations_endpoint_idx").on(table.endpointId, table.firstSeenAt)
|
|
1129
|
+
]
|
|
1130
|
+
);
|
|
1131
|
+
var mcpEndpointChanges = pgTable(
|
|
1132
|
+
"mcp_endpoint_changes",
|
|
1133
|
+
{
|
|
1134
|
+
id: serial("id").primaryKey(),
|
|
1135
|
+
endpointId: integer("endpoint_id").notNull().references(() => mcpRemoteEndpoints.id),
|
|
1136
|
+
kind: text("kind").$type().notNull(),
|
|
1137
|
+
fromKey: text("from_key").notNull(),
|
|
1138
|
+
toKey: text("to_key").notNull(),
|
|
1139
|
+
severity: text("severity").$type().notNull(),
|
|
1140
|
+
summary: text("summary").notNull(),
|
|
1141
|
+
diff: jsonb("diff").$type(),
|
|
1142
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
1143
|
+
},
|
|
1144
|
+
(table) => [
|
|
1145
|
+
uniqueIndex("mcp_endpoint_changes_pair_idx").on(
|
|
1146
|
+
table.endpointId,
|
|
1147
|
+
table.kind,
|
|
1148
|
+
table.fromKey,
|
|
1149
|
+
table.toKey
|
|
1150
|
+
),
|
|
1151
|
+
index("mcp_endpoint_changes_endpoint_idx").on(table.endpointId, table.createdAt),
|
|
1152
|
+
index("mcp_endpoint_changes_created_idx").on(table.createdAt)
|
|
1153
|
+
]
|
|
1154
|
+
);
|
|
1155
|
+
var mcpPins = pgTable(
|
|
1156
|
+
"mcp_pins",
|
|
1157
|
+
{
|
|
1158
|
+
id: serial("id").primaryKey(),
|
|
1159
|
+
ownerId: text("owner_id").notNull(),
|
|
1160
|
+
endpointId: integer("endpoint_id").notNull().references(() => mcpRemoteEndpoints.id),
|
|
1161
|
+
/** Null when the contract was not readable without credentials at pin time. */
|
|
1162
|
+
contentHash: text("content_hash"),
|
|
1163
|
+
authHash: text("auth_hash"),
|
|
1164
|
+
note: text("note"),
|
|
1165
|
+
pinnedAt: ts("pinned_at").notNull().defaultNow(),
|
|
1166
|
+
removedAt: ts("removed_at")
|
|
1167
|
+
},
|
|
1168
|
+
(table) => [
|
|
1169
|
+
uniqueIndex("mcp_pins_owner_endpoint_idx").on(table.ownerId, table.endpointId),
|
|
1170
|
+
index("mcp_pins_endpoint_idx").on(table.endpointId)
|
|
1171
|
+
]
|
|
1172
|
+
);
|
|
1173
|
+
var mcpEndpointChangeAcks = pgTable(
|
|
1174
|
+
"mcp_endpoint_change_acks",
|
|
1175
|
+
{
|
|
1176
|
+
ownerId: text("owner_id").notNull(),
|
|
1177
|
+
changeId: integer("change_id").notNull().references(() => mcpEndpointChanges.id),
|
|
1178
|
+
acknowledgedAt: ts("acknowledged_at").notNull().defaultNow()
|
|
1179
|
+
},
|
|
1180
|
+
(table) => [primaryKey({ columns: [table.ownerId, table.changeId] })]
|
|
1181
|
+
);
|
|
927
1182
|
|
|
928
1183
|
export {
|
|
929
1184
|
packages,
|
|
@@ -940,6 +1195,7 @@ export {
|
|
|
940
1195
|
recommendationOutcomes,
|
|
941
1196
|
askSpendDaily,
|
|
942
1197
|
ownerUsageDaily,
|
|
1198
|
+
repoPolicyDefaults,
|
|
943
1199
|
repos,
|
|
944
1200
|
upgradeRuns,
|
|
945
1201
|
repoAlerts,
|
|
@@ -961,5 +1217,13 @@ export {
|
|
|
961
1217
|
mcpPublicReports,
|
|
962
1218
|
notificationPreferences,
|
|
963
1219
|
notificationChannels,
|
|
1220
|
+
builderScans,
|
|
1221
|
+
mcpRegistryServers,
|
|
1222
|
+
mcpRemoteEndpoints,
|
|
1223
|
+
mcpEndpointServers,
|
|
1224
|
+
mcpEndpointObservations,
|
|
1225
|
+
mcpEndpointChanges,
|
|
1226
|
+
mcpPins,
|
|
1227
|
+
mcpEndpointChangeAcks,
|
|
964
1228
|
schema_exports
|
|
965
1229
|
};
|