@jagilber-org/index-server 1.26.1 → 1.26.4
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/CHANGELOG.md +4 -0
- package/dist/dashboard/client/admin.html +26 -26
- package/package.json +2 -1
- package/scripts/generate-certs.mjs +201 -0
- package/server.json +20 -1
package/CHANGELOG.md
CHANGED
|
@@ -1437,3 +1437,7 @@ No client changes required. Enable `INDEX_SERVER_MEMOIZE=1` (and optionally `IND
|
|
|
1437
1437
|
### Added
|
|
1438
1438
|
|
|
1439
1439
|
- Add --init-cert CLI switch for self-signed dashboard TLS bootstrap (PR #233, issue #232)
|
|
1440
|
+
|
|
1441
|
+
## [1.26.2] - 2026-04-27
|
|
1442
|
+
|
|
1443
|
+
## [1.26.4] - 2026-04-28
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
<meta name="dashboard-build-version" content="1.26.
|
|
4
|
+
<meta name="dashboard-build-version" content="1.26.4-9badd8dd">
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>Index Server Admin</title>
|
|
8
|
-
<link rel="stylesheet" href="css/admin.css?v=1.26.
|
|
9
|
-
<script defer src="js/admin.utils.js?v=1.26.
|
|
10
|
-
<script defer src="js/admin.auth.js?v=1.26.
|
|
11
|
-
<script defer src="js/admin.overview.js?v=1.26.
|
|
12
|
-
<script defer src="js/admin.sessions.js?v=1.26.
|
|
13
|
-
<script defer src="js/admin.monitor.js?v=1.26.
|
|
14
|
-
<script defer src="js/admin.graph.js?v=1.26.
|
|
8
|
+
<link rel="stylesheet" href="css/admin.css?v=1.26.4-9badd8dd">
|
|
9
|
+
<script defer src="js/admin.utils.js?v=1.26.4-9badd8dd"></script>
|
|
10
|
+
<script defer src="js/admin.auth.js?v=1.26.4-9badd8dd"></script>
|
|
11
|
+
<script defer src="js/admin.overview.js?v=1.26.4-9badd8dd"></script>
|
|
12
|
+
<script defer src="js/admin.sessions.js?v=1.26.4-9badd8dd"></script>
|
|
13
|
+
<script defer src="js/admin.monitor.js?v=1.26.4-9badd8dd"></script>
|
|
14
|
+
<script defer src="js/admin.graph.js?v=1.26.4-9badd8dd"></script>
|
|
15
15
|
<script defer src="js/marked.umd.js"></script>
|
|
16
|
-
<script defer src="js/admin.instructions.js?v=1.26.
|
|
17
|
-
<script defer src="js/admin.logs.js?v=1.26.
|
|
18
|
-
<script defer src="js/admin.maintenance.js?v=1.26.
|
|
19
|
-
<script defer src="js/admin.config.js?v=1.26.
|
|
20
|
-
<script defer src="js/admin.performance.js?v=1.26.
|
|
21
|
-
<script defer src="js/admin.instances.js?v=1.26.
|
|
22
|
-
<script defer src="js/admin.embeddings.js?v=1.26.
|
|
23
|
-
<script defer src="js/admin.messaging.js?v=1.26.
|
|
24
|
-
<script defer src="js/admin.sqlite.js?v=1.26.
|
|
25
|
-
<script defer src="js/admin.boot.js?v=1.26.
|
|
26
|
-
<script defer src="js/admin.feedback.js?v=1.26.
|
|
16
|
+
<script defer src="js/admin.instructions.js?v=1.26.4-9badd8dd"></script>
|
|
17
|
+
<script defer src="js/admin.logs.js?v=1.26.4-9badd8dd"></script>
|
|
18
|
+
<script defer src="js/admin.maintenance.js?v=1.26.4-9badd8dd"></script>
|
|
19
|
+
<script defer src="js/admin.config.js?v=1.26.4-9badd8dd"></script>
|
|
20
|
+
<script defer src="js/admin.performance.js?v=1.26.4-9badd8dd"></script>
|
|
21
|
+
<script defer src="js/admin.instances.js?v=1.26.4-9badd8dd"></script>
|
|
22
|
+
<script defer src="js/admin.embeddings.js?v=1.26.4-9badd8dd"></script>
|
|
23
|
+
<script defer src="js/admin.messaging.js?v=1.26.4-9badd8dd"></script>
|
|
24
|
+
<script defer src="js/admin.sqlite.js?v=1.26.4-9badd8dd"></script>
|
|
25
|
+
<script defer src="js/admin.boot.js?v=1.26.4-9badd8dd"></script>
|
|
26
|
+
<script defer src="js/admin.feedback.js?v=1.26.4-9badd8dd"></script>
|
|
27
27
|
</head>
|
|
28
28
|
<body>
|
|
29
29
|
<div class="admin-container admin-root">
|
|
@@ -879,10 +879,10 @@
|
|
|
879
879
|
}
|
|
880
880
|
}
|
|
881
881
|
|
|
882
|
-
// Graph logic was extracted to js/admin.graph.js?v=1.26.
|
|
882
|
+
// Graph logic was extracted to js/admin.graph.js?v=1.26.4-9badd8dd
|
|
883
883
|
// Functions available globally: reloadGraphMermaid, initGraphScopeDefaults, copyMermaidSource, toggleGraphEdit, applyGraphEdit, cancelGraphEdit, refreshDrillCategories, loadDrillInstructions, clearSelections
|
|
884
884
|
|
|
885
|
-
<!-- overview functions moved to js/admin.overview.js?v=1.26.
|
|
885
|
+
<!-- overview functions moved to js/admin.overview.js?v=1.26.4-9badd8dd -->
|
|
886
886
|
|
|
887
887
|
// Lightweight overview-level maintenance display (optional)
|
|
888
888
|
// Intentionally minimal to avoid blocking overview rendering.
|
|
@@ -1067,7 +1067,7 @@
|
|
|
1067
1067
|
}
|
|
1068
1068
|
|
|
1069
1069
|
// --- Backup / Restore ---
|
|
1070
|
-
// Extracted to js/admin.maintenance.js?v=1.26.
|
|
1070
|
+
// Extracted to js/admin.maintenance.js?v=1.26.4-9badd8dd
|
|
1071
1071
|
|
|
1072
1072
|
async function performBackup() {
|
|
1073
1073
|
try {
|
|
@@ -1133,7 +1133,7 @@
|
|
|
1133
1133
|
}
|
|
1134
1134
|
|
|
1135
1135
|
async function loadConfiguration() {
|
|
1136
|
-
// Primary implementation in js/admin.config.js?v=1.26.
|
|
1136
|
+
// Primary implementation in js/admin.config.js?v=1.26.4-9badd8dd (loaded via defer).
|
|
1137
1137
|
// This inline fallback only fires if the external script failed to load.
|
|
1138
1138
|
if (window.__configExternalLoaded) return;
|
|
1139
1139
|
try {
|
|
@@ -1193,10 +1193,10 @@
|
|
|
1193
1193
|
return false;
|
|
1194
1194
|
}
|
|
1195
1195
|
|
|
1196
|
-
// Monitoring functions moved to js/admin.monitor.js?v=1.26.
|
|
1196
|
+
// Monitoring functions moved to js/admin.monitor.js?v=1.26.4-9badd8dd
|
|
1197
1197
|
|
|
1198
1198
|
// ===== Log Viewer =====
|
|
1199
|
-
// Extracted to js/admin.logs.js?v=1.26.
|
|
1199
|
+
// Extracted to js/admin.logs.js?v=1.26.4-9badd8dd
|
|
1200
1200
|
|
|
1201
1201
|
// ===== Instruction Management =====
|
|
1202
1202
|
let instructionEditing = null;
|
|
@@ -1693,7 +1693,7 @@
|
|
|
1693
1693
|
setInterval(fetchResourceTrends, 10000);
|
|
1694
1694
|
})();
|
|
1695
1695
|
|
|
1696
|
-
// Instruction management logic extracted to js/admin.instructions.js?v=1.26.
|
|
1696
|
+
// Instruction management logic extracted to js/admin.instructions.js?v=1.26.4-9badd8dd
|
|
1697
1697
|
// Functions exposed globally: loadInstructions, renderInstructionList, editInstruction, saveInstruction, deleteInstruction, etc.
|
|
1698
1698
|
|
|
1699
1699
|
function startAutoRefresh() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jagilber-org/index-server",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.4",
|
|
4
4
|
"mcpName": "io.github.jagilber-org/index-server",
|
|
5
5
|
"description": "MCP instruction indexing server for AI assistant governance — search, CRUD, schema validation, usage tracking, and cross-repo knowledge promotion.",
|
|
6
6
|
"publishConfig": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"templates/",
|
|
19
19
|
"scripts/copy-dashboard-assets.mjs",
|
|
20
20
|
"scripts/setup-hooks.cjs",
|
|
21
|
+
"scripts/generate-certs.mjs",
|
|
21
22
|
"scripts/setup-wizard.mjs",
|
|
22
23
|
"server.json",
|
|
23
24
|
"README.md",
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* generate-certs.mjs — Generate self-signed TLS certificates for Index Server.
|
|
4
|
+
*
|
|
5
|
+
* Creates a CA + server certificate pair in ./certs/ for HTTPS dashboard access.
|
|
6
|
+
* For production, replace with certificates from a real CA.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node scripts/generate-certs.mjs [--hostname <name>] [--days <n>] [--output <dir>]
|
|
10
|
+
*/
|
|
11
|
+
import { execFileSync } from 'child_process';
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
18
|
+
|
|
19
|
+
function parseArgs() {
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const config = {
|
|
22
|
+
hostname: 'localhost',
|
|
23
|
+
days: 365,
|
|
24
|
+
outputDir: path.join(ROOT, 'certs'),
|
|
25
|
+
keySize: 4096,
|
|
26
|
+
};
|
|
27
|
+
for (let i = 0; i < args.length; i++) {
|
|
28
|
+
if (args[i] === '--hostname' && args[i + 1]) config.hostname = args[++i];
|
|
29
|
+
else if (args[i] === '--days' && args[i + 1]) config.days = parseInt(args[++i], 10);
|
|
30
|
+
else if (args[i] === '--output' && args[i + 1]) config.outputDir = path.resolve(args[++i]);
|
|
31
|
+
else if (args[i] === '--key-size' && args[i + 1]) config.keySize = parseInt(args[++i], 10);
|
|
32
|
+
else if (args[i] === '--help') {
|
|
33
|
+
console.log(`Usage: generate-certs.mjs [options]
|
|
34
|
+
--hostname <name> Server hostname (default: localhost)
|
|
35
|
+
--days <n> Certificate validity in days (default: 365)
|
|
36
|
+
--output <dir> Output directory (default: ./certs)
|
|
37
|
+
--key-size <bits> RSA key size (default: 4096)`);
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return config;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const WELL_KNOWN_OPENSSL_DIRS = [
|
|
45
|
+
'C:\\Program Files\\Git\\usr\\bin',
|
|
46
|
+
'C:\\Program Files (x86)\\Git\\usr\\bin',
|
|
47
|
+
'C:\\Program Files\\OpenSSL-Win64\\bin',
|
|
48
|
+
'C:\\Program Files\\OpenSSL\\bin',
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
function checkOpenssl() {
|
|
52
|
+
try {
|
|
53
|
+
execFileSync('openssl', ['version'], { stdio: 'pipe' });
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
// Try well-known paths on Windows
|
|
57
|
+
for (const dir of WELL_KNOWN_OPENSSL_DIRS) {
|
|
58
|
+
const exe = path.join(dir, 'openssl.exe');
|
|
59
|
+
if (fs.existsSync(exe)) {
|
|
60
|
+
console.log(`ℹ️ Found OpenSSL at: ${dir}`);
|
|
61
|
+
process.env.PATH = `${dir}${path.delimiter}${process.env.PATH}`;
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function runOpenSsl(args, options = {}) {
|
|
70
|
+
execFileSync('openssl', args, { stdio: 'pipe', ...options });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function generateCerts(config) {
|
|
74
|
+
const { hostname, days, outputDir, keySize } = config;
|
|
75
|
+
|
|
76
|
+
// Validate hostname to prevent command injection via -subj parameter
|
|
77
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(hostname)) {
|
|
78
|
+
console.error(`❌ Invalid hostname: "${hostname}". Only alphanumeric, dots, hyphens, and underscores allowed.`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
if (!Number.isInteger(days) || days < 1 || days > 3650) {
|
|
82
|
+
console.error(`❌ Invalid days value: "${days}". Expected an integer between 1 and 3650.`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
if (!Number.isInteger(keySize) || ![2048, 3072, 4096].includes(keySize)) {
|
|
86
|
+
console.error(`❌ Invalid key size: "${keySize}". Allowed values: 2048, 3072, 4096.`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Ensure output directory exists
|
|
91
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
92
|
+
|
|
93
|
+
const caKeyPath = path.join(outputDir, 'ca.key');
|
|
94
|
+
const caCertPath = path.join(outputDir, 'ca.crt');
|
|
95
|
+
const serverKeyPath = path.join(outputDir, 'server.key');
|
|
96
|
+
const serverCsrPath = path.join(outputDir, 'server.csr');
|
|
97
|
+
const serverCertPath = path.join(outputDir, 'server.crt');
|
|
98
|
+
const extPath = path.join(outputDir, 'server.ext');
|
|
99
|
+
const cnfPath = path.join(outputDir, 'openssl.cnf');
|
|
100
|
+
|
|
101
|
+
console.log(`\n🔐 Generating TLS certificates for: ${hostname}`);
|
|
102
|
+
console.log(` Output: ${outputDir}`);
|
|
103
|
+
console.log(` Validity: ${days} days`);
|
|
104
|
+
console.log(` Key size: ${keySize} bits\n`);
|
|
105
|
+
|
|
106
|
+
// Create a minimal openssl config to avoid system config issues (Windows compat)
|
|
107
|
+
const cnfContent = `[req]
|
|
108
|
+
distinguished_name = req_dn
|
|
109
|
+
prompt = no
|
|
110
|
+
|
|
111
|
+
[req_dn]
|
|
112
|
+
C = US
|
|
113
|
+
ST = Dev
|
|
114
|
+
L = Local
|
|
115
|
+
O = IndexServer
|
|
116
|
+
`;
|
|
117
|
+
fs.writeFileSync(cnfPath, cnfContent, 'utf8');
|
|
118
|
+
const cnfEnv = { ...process.env, OPENSSL_CONF: cnfPath };
|
|
119
|
+
|
|
120
|
+
// Step 1: Generate CA private key
|
|
121
|
+
console.log('1/5 Generating CA private key...');
|
|
122
|
+
runOpenSsl(['genrsa', '-out', caKeyPath, String(keySize)], { env: cnfEnv });
|
|
123
|
+
|
|
124
|
+
// Step 2: Generate CA certificate
|
|
125
|
+
console.log('2/5 Generating CA certificate...');
|
|
126
|
+
runOpenSsl([
|
|
127
|
+
'req', '-x509', '-new', '-nodes', '-key', caKeyPath, '-sha256', '-days', String(days),
|
|
128
|
+
'-subj', '/C=US/ST=Dev/L=Local/O=IndexServer/OU=Dev/CN=IndexServerCA',
|
|
129
|
+
'-config', cnfPath, '-out', caCertPath,
|
|
130
|
+
], { env: cnfEnv });
|
|
131
|
+
|
|
132
|
+
// Step 3: Generate server private key
|
|
133
|
+
console.log('3/5 Generating server private key...');
|
|
134
|
+
runOpenSsl(['genrsa', '-out', serverKeyPath, String(keySize)], { env: cnfEnv });
|
|
135
|
+
|
|
136
|
+
// Step 4: Generate server CSR
|
|
137
|
+
console.log('4/5 Generating server CSR...');
|
|
138
|
+
runOpenSsl([
|
|
139
|
+
'req', '-new', '-key', serverKeyPath,
|
|
140
|
+
'-subj', `/C=US/ST=Dev/L=Local/O=IndexServer/OU=Server/CN=${hostname}`,
|
|
141
|
+
'-config', cnfPath, '-out', serverCsrPath,
|
|
142
|
+
], { env: cnfEnv });
|
|
143
|
+
|
|
144
|
+
// Step 5: Create extensions file and sign server cert
|
|
145
|
+
console.log('5/5 Signing server certificate...');
|
|
146
|
+
const extContent = `authorityKeyIdentifier=keyid,issuer
|
|
147
|
+
basicConstraints=CA:FALSE
|
|
148
|
+
keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
|
|
149
|
+
subjectAltName=@alt_names
|
|
150
|
+
|
|
151
|
+
[alt_names]
|
|
152
|
+
DNS.1=${hostname}
|
|
153
|
+
DNS.2=*.${hostname}
|
|
154
|
+
IP.1=127.0.0.1
|
|
155
|
+
IP.2=::1`;
|
|
156
|
+
|
|
157
|
+
fs.writeFileSync(extPath, extContent, 'utf8');
|
|
158
|
+
|
|
159
|
+
runOpenSsl([
|
|
160
|
+
'x509', '-req', '-in', serverCsrPath, '-CA', caCertPath, '-CAkey', caKeyPath,
|
|
161
|
+
'-CAcreateserial', '-out', serverCertPath, '-days', String(days), '-sha256', '-extfile', extPath,
|
|
162
|
+
], { env: cnfEnv });
|
|
163
|
+
|
|
164
|
+
// Cleanup intermediate files
|
|
165
|
+
try { fs.unlinkSync(serverCsrPath); } catch { /* ok */ }
|
|
166
|
+
try { fs.unlinkSync(extPath); } catch { /* ok */ }
|
|
167
|
+
try { fs.unlinkSync(cnfPath); } catch { /* ok */ }
|
|
168
|
+
try { fs.unlinkSync(path.join(outputDir, 'ca.srl')); } catch { /* ok */ }
|
|
169
|
+
|
|
170
|
+
// Set restrictive permissions on private keys
|
|
171
|
+
try {
|
|
172
|
+
fs.chmodSync(caKeyPath, 0o600);
|
|
173
|
+
fs.chmodSync(serverKeyPath, 0o600);
|
|
174
|
+
} catch { /* Windows doesn't support chmod */ }
|
|
175
|
+
|
|
176
|
+
console.log('\n✅ TLS certificates generated successfully:');
|
|
177
|
+
console.log(` CA cert: ${caCertPath}`);
|
|
178
|
+
console.log(` Server cert: ${serverCertPath}`);
|
|
179
|
+
console.log(` Server key: ${serverKeyPath}`);
|
|
180
|
+
console.log(` CA key: ${caKeyPath}`);
|
|
181
|
+
console.log('\nTo use with Docker:');
|
|
182
|
+
console.log(' docker compose --profile tls up -d');
|
|
183
|
+
console.log('\nTo use standalone:');
|
|
184
|
+
console.log(` INDEX_SERVER_DASHBOARD_TLS=1 \\`);
|
|
185
|
+
console.log(` INDEX_SERVER_DASHBOARD_TLS_CERT=${serverCertPath} \\`);
|
|
186
|
+
console.log(` INDEX_SERVER_DASHBOARD_TLS_KEY=${serverKeyPath} \\`);
|
|
187
|
+
console.log(' node dist/server/index-server.js --dashboard');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Main
|
|
191
|
+
const config = parseArgs();
|
|
192
|
+
if (!checkOpenssl()) {
|
|
193
|
+
console.error('❌ OpenSSL is not installed or not in PATH.');
|
|
194
|
+
console.error(' Install OpenSSL and try again.');
|
|
195
|
+
console.error(' Options:');
|
|
196
|
+
console.error(' - Install Git for Windows (includes OpenSSL): https://git-scm.com/download/win');
|
|
197
|
+
console.error(' - Install OpenSSL directly: https://slproweb.com/products/Win32OpenSSL.html');
|
|
198
|
+
console.error(' - On Linux/macOS: sudo apt install openssl / brew install openssl');
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
generateCerts(config);
|
package/server.json
CHANGED
|
@@ -1 +1,20 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.jagilber-org/index-server",
|
|
4
|
+
"description": "MCP instruction indexing server for AI assistant governance — search, CRUD, schema validation, usage tracking, and cross-repo knowledge promotion.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "https://github.com/jagilber-org/index-server",
|
|
7
|
+
"source": "github"
|
|
8
|
+
},
|
|
9
|
+
"version": "1.26.4",
|
|
10
|
+
"packages": [
|
|
11
|
+
{
|
|
12
|
+
"registryType": "npm",
|
|
13
|
+
"identifier": "@jagilber-org/index-server",
|
|
14
|
+
"version": "1.26.4",
|
|
15
|
+
"transport": {
|
|
16
|
+
"type": "stdio"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|