@jagilber-org/index-server 1.22.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.
Files changed (190) hide show
  1. package/CHANGELOG.md +91 -2
  2. package/CODE_OF_CONDUCT.md +2 -0
  3. package/CONTRIBUTING.md +32 -2
  4. package/README.md +82 -19
  5. package/SECURITY.md +17 -5
  6. package/dist/config/dashboardConfig.d.ts +3 -0
  7. package/dist/config/dashboardConfig.js +3 -0
  8. package/dist/config/defaultValues.d.ts +1 -1
  9. package/dist/config/defaultValues.js +1 -1
  10. package/dist/config/featureConfig.d.ts +2 -0
  11. package/dist/config/featureConfig.js +6 -1
  12. package/dist/config/runtimeConfig.d.ts +1 -1
  13. package/dist/config/runtimeConfig.js +8 -9
  14. package/dist/dashboard/client/admin.html +170 -53
  15. package/dist/dashboard/client/css/admin.css +132 -0
  16. package/dist/dashboard/client/js/admin.auth.js +25 -11
  17. package/dist/dashboard/client/js/admin.config.js +1 -1
  18. package/dist/dashboard/client/js/admin.feedback.js +328 -0
  19. package/dist/dashboard/client/js/admin.graph.js +120 -18
  20. package/dist/dashboard/client/js/admin.instructions.js +27 -13
  21. package/dist/dashboard/client/js/admin.logs.js +1 -5
  22. package/dist/dashboard/client/js/admin.maintenance.js +53 -8
  23. package/dist/dashboard/client/js/admin.messaging.js +1 -4
  24. package/dist/dashboard/client/js/admin.overview.js +5 -1
  25. package/dist/dashboard/client/js/admin.sessions.js +1 -1
  26. package/dist/dashboard/client/js/admin.utils.js +43 -1
  27. package/dist/dashboard/client/js/mermaid.min.js +813 -537
  28. package/dist/dashboard/export/DataExporter.js +2 -1
  29. package/dist/dashboard/server/AdminPanel.d.ts +3 -0
  30. package/dist/dashboard/server/AdminPanel.js +132 -35
  31. package/dist/dashboard/server/ApiRoutes.js +40 -9
  32. package/dist/dashboard/server/DashboardServer.js +1 -1
  33. package/dist/dashboard/server/FileMetricsStorage.d.ts +19 -0
  34. package/dist/dashboard/server/FileMetricsStorage.js +52 -5
  35. package/dist/dashboard/server/HttpTransport.js +6 -0
  36. package/dist/dashboard/server/InstanceManager.js +7 -2
  37. package/dist/dashboard/server/KnowledgeStore.js +7 -2
  38. package/dist/dashboard/server/MetricsCollector.d.ts +16 -0
  39. package/dist/dashboard/server/MetricsCollector.js +113 -17
  40. package/dist/dashboard/server/legacyDashboardHtml.js +7 -2
  41. package/dist/dashboard/server/middleware/ensureLoadedMiddleware.d.ts +1 -1
  42. package/dist/dashboard/server/middleware/ensureLoadedMiddleware.js +8 -3
  43. package/dist/dashboard/server/routes/admin.feedback.routes.d.ts +15 -0
  44. package/dist/dashboard/server/routes/admin.feedback.routes.js +188 -0
  45. package/dist/dashboard/server/routes/admin.routes.js +35 -27
  46. package/dist/dashboard/server/routes/alerts.routes.js +4 -3
  47. package/dist/dashboard/server/routes/api.feedback.routes.js +2 -1
  48. package/dist/dashboard/server/routes/api.usage.routes.js +8 -7
  49. package/dist/dashboard/server/routes/embeddings.routes.d.ts +2 -1
  50. package/dist/dashboard/server/routes/embeddings.routes.js +18 -9
  51. package/dist/dashboard/server/routes/graph.routes.js +10 -13
  52. package/dist/dashboard/server/routes/index.d.ts +1 -0
  53. package/dist/dashboard/server/routes/index.js +74 -39
  54. package/dist/dashboard/server/routes/instances.routes.js +2 -1
  55. package/dist/dashboard/server/routes/instructions.routes.js +46 -27
  56. package/dist/dashboard/server/routes/knowledge.routes.js +4 -3
  57. package/dist/dashboard/server/routes/logs.routes.js +5 -4
  58. package/dist/dashboard/server/routes/messaging.routes.js +15 -14
  59. package/dist/dashboard/server/routes/metrics.routes.js +14 -13
  60. package/dist/dashboard/server/routes/scripts.routes.js +6 -3
  61. package/dist/dashboard/server/routes/status.routes.js +5 -4
  62. package/dist/dashboard/server/routes/synthetic.routes.js +3 -2
  63. package/dist/dashboard/server/routes/usage.routes.js +2 -1
  64. package/dist/dashboard/server/utils/escapeHtml.d.ts +1 -0
  65. package/dist/dashboard/server/utils/escapeHtml.js +11 -0
  66. package/dist/dashboard/server/utils/pathContainment.d.ts +1 -0
  67. package/dist/dashboard/server/utils/pathContainment.js +15 -0
  68. package/dist/dashboard/server/wsInit.js +2 -2
  69. package/dist/lib/mcpStdioLogging.d.ts +165 -0
  70. package/dist/lib/mcpStdioLogging.js +287 -0
  71. package/dist/schemas/index.d.ts +37 -2
  72. package/dist/schemas/index.js +27 -3
  73. package/dist/server/backgroundServicesStartup.d.ts +7 -1
  74. package/dist/server/backgroundServicesStartup.js +25 -8
  75. package/dist/server/certInit.d.ts +97 -0
  76. package/dist/server/certInit.js +359 -0
  77. package/dist/server/certInit.types.d.ts +92 -0
  78. package/dist/server/certInit.types.js +34 -0
  79. package/dist/server/handshake/fallbackFrames.d.ts +31 -0
  80. package/dist/server/handshake/fallbackFrames.js +38 -0
  81. package/dist/server/handshake/initializeDetector.d.ts +31 -0
  82. package/dist/server/handshake/initializeDetector.js +88 -0
  83. package/dist/server/handshake/protocol.d.ts +15 -0
  84. package/dist/server/handshake/protocol.js +37 -0
  85. package/dist/server/handshake/readyEmitter.d.ts +6 -0
  86. package/dist/server/handshake/readyEmitter.js +88 -0
  87. package/dist/server/handshake/safetyFallbacks.d.ts +1 -0
  88. package/dist/server/handshake/safetyFallbacks.js +134 -0
  89. package/dist/server/handshake/stdinSniffer.d.ts +1 -0
  90. package/dist/server/handshake/stdinSniffer.js +260 -0
  91. package/dist/server/handshake/tracing.d.ts +16 -0
  92. package/dist/server/handshake/tracing.js +95 -0
  93. package/dist/server/handshakeManager.d.ts +23 -23
  94. package/dist/server/handshakeManager.js +36 -466
  95. package/dist/server/index-server.d.ts +23 -0
  96. package/dist/server/index-server.js +194 -9
  97. package/dist/server/mcpReadOnlySurfaces.d.ts +44 -0
  98. package/dist/server/mcpReadOnlySurfaces.js +297 -0
  99. package/dist/server/sdkServer.js +69 -7
  100. package/dist/server/transport.d.ts +5 -6
  101. package/dist/server/transport.js +46 -64
  102. package/dist/server/transportFactory.d.ts +3 -9
  103. package/dist/server/transportFactory.js +18 -380
  104. package/dist/services/atomicFs.d.ts +3 -0
  105. package/dist/services/atomicFs.js +171 -13
  106. package/dist/services/auditLog.d.ts +17 -2
  107. package/dist/services/auditLog.js +75 -14
  108. package/dist/services/bootstrapGating.js +1 -1
  109. package/dist/services/categoryRules.d.ts +10 -0
  110. package/dist/services/categoryRules.js +17 -0
  111. package/dist/services/classificationService.js +7 -5
  112. package/dist/services/embeddingService.d.ts +27 -11
  113. package/dist/services/embeddingService.js +51 -14
  114. package/dist/services/feedbackStorage.d.ts +39 -0
  115. package/dist/services/feedbackStorage.js +88 -0
  116. package/dist/services/handlers/instructions.add.js +429 -317
  117. package/dist/services/handlers/instructions.groom.js +128 -31
  118. package/dist/services/handlers/instructions.import.js +56 -23
  119. package/dist/services/handlers/instructions.patch.js +43 -32
  120. package/dist/services/handlers/instructions.query.js +20 -29
  121. package/dist/services/handlers/instructions.shared.d.ts +54 -0
  122. package/dist/services/handlers/instructions.shared.js +126 -1
  123. package/dist/services/handlers.activation.js +83 -81
  124. package/dist/services/handlers.dashboardConfig.d.ts +2 -2
  125. package/dist/services/handlers.dashboardConfig.js +1 -2
  126. package/dist/services/handlers.diagnostics.js +75 -54
  127. package/dist/services/handlers.feedback.d.ts +4 -11
  128. package/dist/services/handlers.feedback.js +11 -333
  129. package/dist/services/handlers.gates.js +69 -37
  130. package/dist/services/handlers.graph.js +2 -2
  131. package/dist/services/handlers.help.js +2 -2
  132. package/dist/services/handlers.instructionSchema.js +4 -2
  133. package/dist/services/handlers.integrity.js +42 -22
  134. package/dist/services/handlers.messaging.js +1 -1
  135. package/dist/services/handlers.metrics.js +51 -6
  136. package/dist/services/handlers.prompt.js +10 -2
  137. package/dist/services/handlers.search.js +94 -44
  138. package/dist/services/handlers.trace.js +1 -1
  139. package/dist/services/handlers.usage.js +38 -7
  140. package/dist/services/indexContext.d.ts +21 -1
  141. package/dist/services/indexContext.js +263 -78
  142. package/dist/services/indexLoader.d.ts +1 -0
  143. package/dist/services/indexLoader.js +28 -8
  144. package/dist/services/instructionRecordValidation.d.ts +39 -0
  145. package/dist/services/instructionRecordValidation.js +388 -0
  146. package/dist/services/instructions.dispatcher.js +4 -4
  147. package/dist/services/loaderSchemaValidator.d.ts +15 -0
  148. package/dist/services/loaderSchemaValidator.js +69 -0
  149. package/dist/services/logger.js +11 -2
  150. package/dist/services/mcpLogBridge.d.ts +49 -0
  151. package/dist/services/mcpLogBridge.js +83 -0
  152. package/dist/services/ownershipService.js +18 -8
  153. package/dist/services/performanceBaseline.js +23 -22
  154. package/dist/services/promptReviewService.d.ts +3 -1
  155. package/dist/services/promptReviewService.js +41 -13
  156. package/dist/services/regexSafety.d.ts +6 -0
  157. package/dist/services/regexSafety.js +46 -0
  158. package/dist/services/seedBootstrap.js +1 -1
  159. package/dist/services/storage/factory.d.ts +14 -1
  160. package/dist/services/storage/factory.js +61 -1
  161. package/dist/services/storage/jsonEmbeddingStore.d.ts +15 -0
  162. package/dist/services/storage/jsonEmbeddingStore.js +83 -0
  163. package/dist/services/storage/jsonFileStore.d.ts +3 -1
  164. package/dist/services/storage/jsonFileStore.js +8 -6
  165. package/dist/services/storage/migrationEngine.d.ts +13 -0
  166. package/dist/services/storage/migrationEngine.js +31 -0
  167. package/dist/services/storage/sqliteEmbeddingStore.d.ts +30 -0
  168. package/dist/services/storage/sqliteEmbeddingStore.js +222 -0
  169. package/dist/services/storage/sqliteStore.d.ts +3 -1
  170. package/dist/services/storage/sqliteStore.js +2 -2
  171. package/dist/services/storage/types.d.ts +48 -1
  172. package/dist/services/toolRegistry.js +77 -67
  173. package/dist/services/toolRegistry.zod.js +89 -86
  174. package/dist/services/tracing.js +5 -4
  175. package/dist/utils/envUtils.d.ts +4 -0
  176. package/dist/utils/envUtils.js +7 -0
  177. package/dist/utils/memoryMonitor.js +11 -10
  178. package/package.json +12 -4
  179. package/schemas/instruction.schema.json +38 -1
  180. package/scripts/copy-dashboard-assets.mjs +1 -1
  181. package/scripts/dist/README.md +1 -1
  182. package/scripts/generate-certs.mjs +201 -0
  183. package/scripts/setup-wizard.mjs +781 -0
  184. package/server.json +20 -0
  185. package/dist/externalClientLib.d.ts +0 -1
  186. package/dist/externalClientLib.js +0 -2
  187. package/dist/portableClientWrapper.d.ts +0 -1
  188. package/dist/portableClientWrapper.js +0 -2
  189. package/dist/services/indexingService.d.ts +0 -1
  190. package/dist/services/indexingService.js +0 -2
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ /**
4
+ * mcpStdioLogging — Generic MCP stdio transport logging solution.
5
+ *
6
+ * Drop-in module for ANY MCP server using stdio transport that wants proper
7
+ * log-level display in VS Code (or any MCP client that reads stderr).
8
+ *
9
+ * ## Problem
10
+ *
11
+ * VS Code's MCP host (`extHostMcpNode.ts`) hardcodes ALL stderr output as
12
+ * `LogLevel.Warning` with prefix `[server stderr]`. There is no configuration,
13
+ * no level detection, no opt-out. Every byte on stderr becomes a warning.
14
+ *
15
+ * The MCP protocol provides `notifications/message` with a `level` field.
16
+ * VS Code's `translateMcpLogMessage()` correctly maps those levels to proper
17
+ * log output (debug, info, warning, error). Other clients (Claude Desktop,
18
+ * Cursor, etc.) also respect `notifications/message` levels.
19
+ *
20
+ * ## Solution
21
+ *
22
+ * 1. Intercept `process.stderr.write` at module import time (before any other
23
+ * module can write to stderr).
24
+ * 2. Buffer all pre-handshake stderr lines in memory.
25
+ * 3. After the MCP handshake completes, replay the buffer through
26
+ * `server.sendLoggingMessage()` and route all future stderr the same way.
27
+ * 4. Infer severity from content (NDJSON level field, keyword patterns).
28
+ * 5. On transport failure, deactivate and restore original stderr.
29
+ *
30
+ * ## Usage (3 steps)
31
+ *
32
+ * ```typescript
33
+ * // 1. Import FIRST — before any module that writes to stderr
34
+ * import { McpStdioLogger } from './lib/mcpStdioLogging';
35
+ * const logger = new McpStdioLogger({ serverName: 'my-server' });
36
+ *
37
+ * // 2. After creating the MCP SDK server, register it
38
+ * const server = new Server({ name: 'my-server', version }, { capabilities: { logging: {} } });
39
+ * logger.registerServer(server);
40
+ *
41
+ * // 3. After the handshake completes (initialize response sent), activate
42
+ * logger.activate();
43
+ * ```
44
+ *
45
+ * ## Requirements
46
+ *
47
+ * - Server must declare `logging: {}` in capabilities so clients know to
48
+ * accept `notifications/message`.
49
+ * - Server object must have `sendLoggingMessage({ level, logger?, data })`.
50
+ * - Module must be imported before `logPrefix` or any other stderr-producing module.
51
+ *
52
+ * @module mcpStdioLogging
53
+ */
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.McpStdioLogger = void 0;
56
+ exports.defaultInferLevel = defaultInferLevel;
57
+ // ---------------------------------------------------------------------------
58
+ // Built-in level inference heuristic
59
+ // ---------------------------------------------------------------------------
60
+ /**
61
+ * Infer MCP logging level from a raw stderr line.
62
+ *
63
+ * Priority:
64
+ * 1. NDJSON with `"level"` field → map to MCP level
65
+ * 2. Keyword patterns (ERROR, WARN, DEBUG, trace) → corresponding level
66
+ * 3. Default → 'info'
67
+ */
68
+ function defaultInferLevel(line) {
69
+ // Check for NDJSON with "level" field
70
+ if (line.startsWith('{')) {
71
+ const m = /"level"\s*:\s*"(TRACE|DEBUG|INFO|WARN|WARNING|ERROR|FATAL|info|warning|error|debug|notice|critical|alert|emergency)"/i.exec(line);
72
+ if (m) {
73
+ const l = m[1].toUpperCase();
74
+ if (l === 'TRACE' || l === 'DEBUG')
75
+ return 'debug';
76
+ if (l === 'INFO' || l === 'NOTICE')
77
+ return 'info';
78
+ if (l === 'WARN' || l === 'WARNING')
79
+ return 'warning';
80
+ if (l === 'ERROR')
81
+ return 'error';
82
+ if (l === 'FATAL' || l === 'CRITICAL')
83
+ return 'critical';
84
+ if (l === 'ALERT')
85
+ return 'alert';
86
+ if (l === 'EMERGENCY')
87
+ return 'emergency';
88
+ }
89
+ }
90
+ // Keyword patterns in plain text
91
+ if (/\bERROR\b|\bFATAL\b/i.test(line))
92
+ return 'error';
93
+ if (/\bWARN\b/i.test(line))
94
+ return 'warning';
95
+ if (/\bDEBUG\b|\btrace\b/i.test(line))
96
+ return 'debug';
97
+ return 'info';
98
+ }
99
+ // ---------------------------------------------------------------------------
100
+ // McpStdioLogger class
101
+ // ---------------------------------------------------------------------------
102
+ /**
103
+ * Manages stderr interception, buffering, and MCP protocol log routing
104
+ * for any MCP server using stdio transport.
105
+ *
106
+ * Designed to be instantiated once, as early as possible in the server's
107
+ * entry point, before any module writes to stderr.
108
+ */
109
+ class McpStdioLogger {
110
+ _server = null;
111
+ _active = false;
112
+ _intercepting = false;
113
+ _buffer = [];
114
+ _originalStderrWrite;
115
+ _serverName;
116
+ _maxBufferSize;
117
+ _inferLevel;
118
+ constructor(options = {}) {
119
+ this._serverName = options.serverName ?? 'mcp-server';
120
+ this._maxBufferSize = options.maxBufferSize ?? 500;
121
+ this._inferLevel = options.inferLevel ?? defaultInferLevel;
122
+ this._originalStderrWrite = process.stderr.write.bind(process.stderr);
123
+ if (options.interceptImmediately !== false) {
124
+ this.interceptStderr();
125
+ }
126
+ }
127
+ // -----------------------------------------------------------------------
128
+ // Public API
129
+ // -----------------------------------------------------------------------
130
+ /**
131
+ * Start intercepting process.stderr.write.
132
+ * Called automatically on construction unless `interceptImmediately: false`.
133
+ * Safe to call multiple times (idempotent).
134
+ */
135
+ interceptStderr() {
136
+ if (this._intercepting)
137
+ return;
138
+ this._intercepting = true;
139
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
140
+ const self = this;
141
+ process.stderr.write = ((chunk, encodingOrCb, cb) => {
142
+ const text = typeof chunk === 'string'
143
+ ? chunk
144
+ : Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk);
145
+ const lines = text.split(/\r?\n/);
146
+ for (const line of lines) {
147
+ const trimmed = line.trim();
148
+ if (!trimmed)
149
+ continue;
150
+ if (self._active && self._server) {
151
+ // Bridge is live — send directly via MCP protocol
152
+ try {
153
+ self._server.sendLoggingMessage({
154
+ level: self._inferLevel(trimmed),
155
+ logger: self._serverName,
156
+ data: trimmed,
157
+ });
158
+ }
159
+ catch {
160
+ // Transport failed — deactivate and fall back to real stderr
161
+ self._active = false;
162
+ self._intercepting = false;
163
+ process.stderr.write = self._originalStderrWrite;
164
+ return self._originalStderrWrite(chunk, encodingOrCb, cb);
165
+ }
166
+ }
167
+ else {
168
+ // Pre-handshake — buffer the line (don't write to stderr)
169
+ self._buffer.push({ level: self._inferLevel(trimmed), data: trimmed });
170
+ // Enforce buffer size limit
171
+ if (self._buffer.length > self._maxBufferSize) {
172
+ self._buffer.shift();
173
+ }
174
+ }
175
+ }
176
+ // Invoke callback if provided
177
+ const callback = typeof encodingOrCb === 'function' ? encodingOrCb : cb;
178
+ if (typeof callback === 'function')
179
+ callback();
180
+ return true;
181
+ });
182
+ }
183
+ /**
184
+ * Register the MCP SDK server instance.
185
+ * Must be called after server creation but before activation.
186
+ * The server must have a `sendLoggingMessage()` method.
187
+ */
188
+ registerServer(server) {
189
+ this._server = server;
190
+ }
191
+ /**
192
+ * Activate the bridge: replay buffered stderr and route all future
193
+ * output through `server.sendLoggingMessage()`.
194
+ *
195
+ * Call this after the MCP handshake completes (initialize response sent).
196
+ * No-op if server is not registered or lacks sendLoggingMessage.
197
+ */
198
+ activate() {
199
+ if (!this._server || typeof this._server.sendLoggingMessage !== 'function')
200
+ return;
201
+ this._active = true;
202
+ this._replayBuffer();
203
+ }
204
+ /**
205
+ * Returns true when the bridge is active and logs route through MCP protocol.
206
+ */
207
+ get isActive() {
208
+ return this._active;
209
+ }
210
+ /**
211
+ * Send a structured log message through the MCP protocol.
212
+ * Use this from your application logger instead of console.error/stderr.
213
+ * No-op if the bridge is not active.
214
+ *
215
+ * @param level - MCP logging level
216
+ * @param data - Log payload (string or object)
217
+ */
218
+ log(level, data) {
219
+ if (!this._active || !this._server)
220
+ return;
221
+ try {
222
+ this._server.sendLoggingMessage({
223
+ level,
224
+ logger: this._serverName,
225
+ data,
226
+ });
227
+ }
228
+ catch {
229
+ // Transport failed — deactivate to avoid repeated failures
230
+ this._active = false;
231
+ }
232
+ }
233
+ /**
234
+ * Write directly to the ORIGINAL process.stderr, bypassing the interceptor.
235
+ * Use this when you need stderr output visible to VS Code's Output panel
236
+ * without triggering the MCP routing/buffering pipeline.
237
+ */
238
+ writeOriginalStderr(data) {
239
+ try {
240
+ this._originalStderrWrite(data.endsWith('\n') ? data : data + '\n');
241
+ }
242
+ catch { /* ignore */ }
243
+ }
244
+ /**
245
+ * Restore original stderr and deactivate the bridge.
246
+ * Useful for testing cleanup or graceful shutdown.
247
+ */
248
+ restore() {
249
+ process.stderr.write = this._originalStderrWrite;
250
+ this._active = false;
251
+ this._intercepting = false;
252
+ this._buffer.length = 0;
253
+ }
254
+ /**
255
+ * Get the number of currently buffered lines (pre-handshake).
256
+ */
257
+ get bufferSize() {
258
+ return this._buffer.length;
259
+ }
260
+ // -----------------------------------------------------------------------
261
+ // Internal
262
+ // -----------------------------------------------------------------------
263
+ _replayBuffer() {
264
+ while (this._buffer.length > 0) {
265
+ const entry = this._buffer.shift();
266
+ try {
267
+ this._server.sendLoggingMessage({
268
+ level: entry.level,
269
+ logger: this._serverName,
270
+ data: entry.data,
271
+ });
272
+ }
273
+ catch {
274
+ // Transport failed during replay — stop and dump remaining to real stderr
275
+ this._active = false;
276
+ this._intercepting = false;
277
+ process.stderr.write = this._originalStderrWrite;
278
+ for (const remaining of this._buffer) {
279
+ this._originalStderrWrite(remaining.data + '\n');
280
+ }
281
+ this._buffer.length = 0;
282
+ return;
283
+ }
284
+ }
285
+ }
286
+ }
287
+ exports.McpStdioLogger = McpStdioLogger;
@@ -1,7 +1,28 @@
1
1
  export declare const instructionEntry: {
2
2
  readonly type: "object";
3
3
  readonly additionalProperties: false;
4
- readonly required: readonly ["id", "title", "body", "priority", "audience", "requirement", "categories", "sourceHash", "schemaVersion", "createdAt", "updatedAt", "version", "status", "owner", "priorityTier", "classification", "lastReviewedAt", "nextReviewDue", "changeLog", "semanticSummary"];
4
+ readonly $defs: {
5
+ readonly extensionValue: {
6
+ readonly anyOf: readonly [{
7
+ readonly type: "string";
8
+ }, {
9
+ readonly type: "number";
10
+ }, {
11
+ readonly type: "boolean";
12
+ }, {
13
+ readonly type: "array";
14
+ readonly items: {
15
+ readonly $ref: "#/$defs/extensionValue";
16
+ };
17
+ }, {
18
+ readonly type: "object";
19
+ readonly additionalProperties: {
20
+ readonly $ref: "#/$defs/extensionValue";
21
+ };
22
+ }];
23
+ };
24
+ };
25
+ readonly required: readonly ["id", "title", "body", "priority", "audience", "requirement", "categories", "sourceHash", "schemaVersion", "createdAt", "updatedAt", "version", "status", "owner", "priorityTier", "classification", "lastReviewedAt", "nextReviewDue", "changeLog", "semanticSummary", "contentType"];
5
26
  readonly properties: {
6
27
  readonly id: {
7
28
  readonly type: "string";
@@ -31,6 +52,9 @@ export declare const instructionEntry: {
31
52
  readonly type: "string";
32
53
  };
33
54
  };
55
+ readonly primaryCategory: {
56
+ readonly type: "string";
57
+ };
34
58
  readonly sourceHash: {
35
59
  readonly type: "string";
36
60
  };
@@ -58,6 +82,9 @@ export declare const instructionEntry: {
58
82
  readonly riskScore: {
59
83
  readonly type: "number";
60
84
  };
85
+ readonly reviewIntervalDays: {
86
+ readonly type: "number";
87
+ };
61
88
  readonly workspaceId: {
62
89
  readonly type: "string";
63
90
  };
@@ -70,6 +97,9 @@ export declare const instructionEntry: {
70
97
  readonly type: "string";
71
98
  };
72
99
  };
100
+ readonly contentType: {
101
+ readonly enum: readonly ["instruction", "template", "chat-session", "reference", "example", "agent"];
102
+ };
73
103
  readonly version: {
74
104
  readonly type: "string";
75
105
  };
@@ -113,6 +143,9 @@ export declare const instructionEntry: {
113
143
  readonly supersedes: {
114
144
  readonly type: "string";
115
145
  };
146
+ readonly archivedAt: {
147
+ readonly type: "string";
148
+ };
116
149
  readonly semanticSummary: {
117
150
  readonly type: "string";
118
151
  };
@@ -124,7 +157,9 @@ export declare const instructionEntry: {
124
157
  };
125
158
  readonly extensions: {
126
159
  readonly type: "object";
127
- readonly additionalProperties: true;
160
+ readonly additionalProperties: {
161
+ readonly $ref: "#/$defs/extensionValue";
162
+ };
128
163
  };
129
164
  };
130
165
  };
@@ -6,9 +6,20 @@ exports.schemas = exports.instructionEntry = void 0;
6
6
  exports.instructionEntry = {
7
7
  type: 'object',
8
8
  additionalProperties: false,
9
+ $defs: {
10
+ extensionValue: {
11
+ anyOf: [
12
+ { type: 'string' },
13
+ { type: 'number' },
14
+ { type: 'boolean' },
15
+ { type: 'array', items: { $ref: '#/$defs/extensionValue' } },
16
+ { type: 'object', additionalProperties: { $ref: '#/$defs/extensionValue' } }
17
+ ]
18
+ }
19
+ },
9
20
  required: [
10
21
  'id', 'title', 'body', 'priority', 'audience', 'requirement', 'categories', 'sourceHash', 'schemaVersion', 'createdAt', 'updatedAt',
11
- 'version', 'status', 'owner', 'priorityTier', 'classification', 'lastReviewedAt', 'nextReviewDue', 'changeLog', 'semanticSummary'
22
+ 'version', 'status', 'owner', 'priorityTier', 'classification', 'lastReviewedAt', 'nextReviewDue', 'changeLog', 'semanticSummary', 'contentType'
12
23
  ],
13
24
  properties: {
14
25
  id: { type: 'string', minLength: 1 },
@@ -19,6 +30,7 @@ exports.instructionEntry = {
19
30
  audience: { enum: ['individual', 'group', 'all'] },
20
31
  requirement: { enum: ['mandatory', 'critical', 'recommended', 'optional', 'deprecated'] },
21
32
  categories: { type: 'array', items: { type: 'string' } },
33
+ primaryCategory: { type: 'string' },
22
34
  sourceHash: { type: 'string' },
23
35
  schemaVersion: { type: 'string' },
24
36
  deprecatedBy: { type: 'string' },
@@ -28,9 +40,11 @@ exports.instructionEntry = {
28
40
  firstSeenTs: { type: 'string' },
29
41
  lastUsedAt: { type: 'string' },
30
42
  riskScore: { type: 'number' },
43
+ reviewIntervalDays: { type: 'number' },
31
44
  workspaceId: { type: 'string' },
32
45
  userId: { type: 'string' },
33
46
  teamIds: { type: 'array', items: { type: 'string' } },
47
+ contentType: { enum: ['instruction', 'template', 'chat-session', 'reference', 'example', 'agent'] },
34
48
  version: { type: 'string' },
35
49
  status: { enum: ['draft', 'review', 'approved', 'deprecated'] },
36
50
  owner: { type: 'string' },
@@ -40,10 +54,11 @@ exports.instructionEntry = {
40
54
  nextReviewDue: { type: 'string' },
41
55
  changeLog: { type: 'array', items: { type: 'object', required: ['version', 'changedAt', 'summary'], additionalProperties: false, properties: { version: { type: 'string' }, changedAt: { type: 'string' }, summary: { type: 'string' } } } },
42
56
  supersedes: { type: 'string' },
57
+ archivedAt: { type: 'string' },
43
58
  semanticSummary: { type: 'string' },
44
59
  createdByAgent: { type: 'string' },
45
60
  sourceWorkspace: { type: 'string' },
46
- extensions: { type: 'object', additionalProperties: true }
61
+ extensions: { type: 'object', additionalProperties: { $ref: '#/$defs/extensionValue' } }
47
62
  }
48
63
  };
49
64
  // (listLike schema removed after dispatcher consolidation of read-only instruction methods)
@@ -307,7 +322,16 @@ exports.schemas = {
307
322
  } },
308
323
  'index_add': {
309
324
  anyOf: [
310
- { type: 'object', required: ['error'], properties: { error: { type: 'string' }, id: { type: 'string' } }, additionalProperties: true },
325
+ { type: 'object', required: ['error'], properties: {
326
+ error: { type: 'string' },
327
+ id: { type: 'string' },
328
+ success: { const: false },
329
+ message: { type: 'string' },
330
+ validationErrors: { type: 'array', items: { type: 'string' } },
331
+ hints: { type: 'array', items: { type: 'string' } },
332
+ schemaRef: { type: 'string' },
333
+ inputSchema: { type: 'object' }
334
+ }, additionalProperties: true },
311
335
  { type: 'object', required: ['id', 'hash', 'skipped', 'created', 'overwritten'], additionalProperties: false, properties: {
312
336
  id: { type: 'string' }, hash: { type: 'string' }, skipped: { type: 'boolean' }, created: { type: 'boolean' }, overwritten: { type: 'boolean' }
313
337
  } }
@@ -1,3 +1,9 @@
1
1
  import type { RuntimeConfig } from '../config/runtimeConfig';
2
2
  export declare function startOptionalMemoryMonitoring(_runtime: RuntimeConfig): void;
3
- export declare function startDeferredBackgroundServices(runtime: RuntimeConfig): void;
3
+ export declare function startDeferredBackgroundServices(runtime: RuntimeConfig): {
4
+ started: string[];
5
+ errors: {
6
+ service: string;
7
+ error: string;
8
+ }[];
9
+ };
@@ -6,6 +6,7 @@ const envUtils_1 = require("../utils/envUtils");
6
6
  const indexContext_1 = require("../services/indexContext");
7
7
  const autoBackup_1 = require("../services/autoBackup");
8
8
  const memoryMonitor_1 = require("../utils/memoryMonitor");
9
+ const logger_1 = require("../services/logger");
9
10
  function startOptionalMemoryMonitoring(_runtime) {
10
11
  if ((0, envUtils_1.getBooleanEnv)('INDEX_SERVER_DEBUG') || (0, envUtils_1.getBooleanEnv)('INDEX_SERVER_MEMORY_MONITOR')) {
11
12
  try {
@@ -20,32 +21,48 @@ function startOptionalMemoryMonitoring(_runtime) {
20
21
  }
21
22
  }
22
23
  function startDeferredBackgroundServices(runtime) {
24
+ const started = [];
25
+ const errors = [];
23
26
  try {
24
27
  if (runtime.server.indexPolling.enabled) {
25
28
  (0, indexContext_1.startIndexVersionPoller)({
26
29
  proactive: runtime.server.indexPolling.proactive,
27
30
  intervalMs: runtime.server.indexPolling.intervalMs,
28
31
  });
32
+ started.push('indexVersionPoller');
29
33
  if (runtime.logging.diagnostics) {
30
34
  try {
31
35
  process.stderr.write(`[startup] index version poller started proactive=${runtime.server.indexPolling.proactive}\n`);
32
36
  }
33
- catch { /* ignore */ }
37
+ catch (err) {
38
+ (0, logger_1.log)('WARN', `[startup] diagnostics write failed: ${err.message}`);
39
+ }
34
40
  }
35
41
  }
36
42
  else if (runtime.logging.diagnostics) {
37
43
  try {
38
44
  process.stderr.write('[startup] index version poller not enabled (set INDEX_SERVER_ENABLE_INDEX_SERVER_POLLER=1)\n');
39
45
  }
40
- catch { /* ignore */ }
46
+ catch (err) {
47
+ (0, logger_1.log)('WARN', `[startup] diagnostics write failed: ${err.message}`);
48
+ }
41
49
  }
42
50
  }
43
- catch { /* ignore */ }
44
- try {
45
- setImmediate(() => { try {
51
+ catch (err) {
52
+ const detail = err.message;
53
+ (0, logger_1.log)('ERROR', `[startup] index version poller failed to start: ${detail}`, { detail: err.stack });
54
+ errors.push({ service: 'indexVersionPoller', error: detail });
55
+ }
56
+ setImmediate(() => {
57
+ try {
46
58
  (0, autoBackup_1.startAutoBackup)();
59
+ started.push('autoBackup');
47
60
  }
48
- catch { /* ignore */ } });
49
- }
50
- catch { /* ignore */ }
61
+ catch (err) {
62
+ const detail = err.message;
63
+ (0, logger_1.log)('ERROR', `[startup] autoBackup failed to start: ${detail}`, { detail: err.stack });
64
+ errors.push({ service: 'autoBackup', error: detail });
65
+ }
66
+ });
67
+ return { started, errors };
51
68
  }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Certificate bootstrap module for the `--init-cert` CLI switch.
3
+ *
4
+ * Public surface (all exports carry JSDoc per CQ-7):
5
+ * - {@link validateOptions} : merge defaults, validate, resolve absolute paths
6
+ * - {@link parseSan} : split + validate SAN entries
7
+ * - {@link buildOpenSslArgs}: build argv for `openssl req -x509`
8
+ * - {@link preflightOpenssl}: verify openssl is callable on PATH
9
+ * - {@link formatPrintEnv} : produce env-var lines for the operator
10
+ * - {@link runCertInit} : end-to-end pipeline
11
+ *
12
+ * Constitution refs:
13
+ * - SH-4 : every output path is `path.resolve`d and asserted to live under
14
+ * the resolved `certDir`.
15
+ * - SH-6 : this module never disables TLS verification anywhere.
16
+ * - CQ-1 : lives in its own file so `index-server.ts` stays under budget.
17
+ * - CQ-6 : every catch surfaces a typed error; no swallowed exceptions.
18
+ * - OB-3 : failures throw {@link CertInitError} with a stable `code`.
19
+ * - OB-5 : success and skip paths log at INFO; failures log at ERROR.
20
+ */
21
+ import type { CertInitOptions, CertInitResult, PrintEnvFormat } from './certInit.types';
22
+ /**
23
+ * Validate a partial options bag and return a fully-resolved
24
+ * {@link CertInitOptions} suitable for {@link runCertInit}.
25
+ *
26
+ * Defaults are applied for any field omitted by the caller. All paths are
27
+ * `path.resolve`d. The function rejects values that violate the v1 contract:
28
+ * days out of `[MIN_DAYS, MAX_DAYS]`, key-bits not in `{2048, 4096}`, SAN
29
+ * entries without `DNS:` or `IP:` prefix, empty CN, or output paths that
30
+ * escape `certDir` (SH-4).
31
+ *
32
+ * @param input Partial options as parsed from the CLI.
33
+ * @returns Fully-resolved {@link CertInitOptions}.
34
+ * @throws {@link CertInitError} with codes `INVALID_DAYS`,
35
+ * `INVALID_KEY_BITS`, `INVALID_SAN`, `INVALID_CN`, or
36
+ * `PATH_OUTSIDE_CERT_DIR`.
37
+ */
38
+ export declare function validateOptions(input: Partial<CertInitOptions>): CertInitOptions;
39
+ /**
40
+ * Parse a comma-separated SAN string into individual entries, validating that
41
+ * each entry has a recognized `DNS:` or `IP:` prefix.
42
+ *
43
+ * @param raw Raw SAN string from the CLI (e.g. `"DNS:host,IP:127.0.0.1"`).
44
+ * @returns Array of validated SAN entries with surrounding whitespace
45
+ * trimmed.
46
+ * @throws {@link CertInitError} `INVALID_SAN` for empty input, trailing
47
+ * commas, or entries missing a recognized prefix.
48
+ */
49
+ export declare function parseSan(raw: string): string[];
50
+ /**
51
+ * Build the argument array for the OpenSSL `req -x509` invocation that
52
+ * generates a self-signed certificate. The returned array is suitable for
53
+ * `child_process.execFile('openssl', args)` — no shell metacharacters are
54
+ * inserted, and inputs are not interpolated into a command string.
55
+ *
56
+ * @param opts Fully-resolved cert-init options (use {@link validateOptions}
57
+ * to produce these).
58
+ * @returns Argument array for `openssl`.
59
+ */
60
+ export declare function buildOpenSslArgs(opts: CertInitOptions): string[];
61
+ /**
62
+ * Verify that `openssl` is callable on PATH. Used as a preflight before any
63
+ * generation work so that the failure surfaces with a stable
64
+ * `OPENSSL_NOT_FOUND` code rather than a downstream spawn error.
65
+ *
66
+ * @returns The reported version string when openssl is callable.
67
+ * @throws {@link CertInitError} `OPENSSL_NOT_FOUND` otherwise.
68
+ */
69
+ export declare function preflightOpenssl(): string;
70
+ /**
71
+ * Format the env-var lines an operator can paste into their shell after a
72
+ * successful generation, pointing the dashboard at the new cert/key.
73
+ *
74
+ * @param opts Resolved cert-init options.
75
+ * @param format Output format. `'auto'` picks `'powershell'` on Win32,
76
+ * `'posix'` elsewhere.
77
+ * @returns Multi-line string ending with a trailing newline.
78
+ */
79
+ export declare function formatPrintEnv(opts: CertInitOptions, format?: PrintEnvFormat): string;
80
+ /**
81
+ * Execute the full cert-init pipeline: validate options, preflight openssl,
82
+ * create `certDir` if missing, run openssl, set restrictive permissions on
83
+ * POSIX, and emit a structured log line via the existing logger.
84
+ *
85
+ * Idempotency: if `certFile` OR `keyFile` already exists and `force` is false,
86
+ * no openssl invocation is made and a `kind: 'skipped'` result is returned.
87
+ * Treating only the both-exist case as "skip" would clobber a surviving cert
88
+ * when the operator deleted/rotated only the key (or vice versa) — `--force`
89
+ * is required to overwrite *any* existing file.
90
+ *
91
+ * @param input Caller options (typically from the CLI parser). Re-validated
92
+ * internally so direct callers do not need to pre-validate.
93
+ * @returns A {@link CertInitResult} indicating generated vs skipped.
94
+ * @throws {@link CertInitError} for any validation, preflight, or
95
+ * execution failure (codes documented on each helper above).
96
+ */
97
+ export declare function runCertInit(input: Partial<CertInitOptions>): Promise<CertInitResult>;