minutes-mcp 0.25.4 → 0.25.6

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.
@@ -133,6 +133,8 @@ export type CorpusLeaseHooks = {
133
133
  export declare function awaitDeferredCorpusReleasesForTests(timeoutMs?: number): Promise<boolean>;
134
134
  /** Test-only: the live retained-corpus charge, for leak assertions. */
135
135
  export declare function reservedCorpusMemoryBytesForTests(): number;
136
+ /** @internal Pure policy seam for test-harness gate regression coverage. */
137
+ export declare function resolveAuthorizationTimeoutMsForTest(timeoutMs: number | undefined, environment: Readonly<NodeJS.ProcessEnv>): number;
136
138
  export type CorpusLeaseWorkerRequest = Readonly<{
137
139
  root: string;
138
140
  budgets: Readonly<CorpusReadBudgets>;
@@ -9,6 +9,7 @@ import { nodeChildEnvironment } from "./node-child.js";
9
9
  const MAX_AUTHORIZATION_ATTEMPTS = 2;
10
10
  const DEFAULT_FENCE_TIMEOUT_MS = 5_000;
11
11
  const DEFAULT_AUTHORIZATION_TIMEOUT_MS = 15_000;
12
+ const MAX_TEST_HARNESS_AUTHORIZATION_TIMEOUT_MS = 120_000;
12
13
  const MAX_ACTIVE_WATCHERS = 64;
13
14
  // Snapshot content is retained as JavaScript strings, whose backing storage
14
15
  // may require two bytes per source byte. Reserve that worst case for the full
@@ -185,12 +186,39 @@ function resolveFenceTimeout(timeoutMs) {
185
186
  }
186
187
  return Math.min(requested, DEFAULT_FENCE_TIMEOUT_MS);
187
188
  }
188
- function authorizationDeadline(timeoutMs) {
189
- const requested = timeoutMs ?? DEFAULT_AUTHORIZATION_TIMEOUT_MS;
189
+ function resolveAuthorizationTimeoutMs(timeoutMs, environment = process.env) {
190
+ const configuredOverride = environment.MINUTES_CORPUS_AUTH_TIMEOUT_MS;
191
+ // A longer deadline is test infrastructure, not application configuration.
192
+ // Requiring both markers keeps an ambient production environment variable
193
+ // from weakening the fail-closed 15 second cap. Only the repository's test
194
+ // harness sets this pair; the spawned lease worker inherits it from the
195
+ // parent. Invalid gated values fail closed instead of silently relaxing or
196
+ // changing the requested budget.
197
+ const testHarnessOverride = environment.NODE_ENV === "test" &&
198
+ environment.MINUTES_TEST_HARNESS === "1" &&
199
+ configuredOverride !== undefined
200
+ ? configuredOverride
201
+ : undefined;
202
+ if (testHarnessOverride !== undefined &&
203
+ !/^[1-9]\d*$/.test(testHarnessOverride)) {
204
+ throw new Error("Access denied: invalid meeting corpus authorization timeout");
205
+ }
206
+ const cap = testHarnessOverride === undefined
207
+ ? DEFAULT_AUTHORIZATION_TIMEOUT_MS
208
+ : Math.min(Number(testHarnessOverride), MAX_TEST_HARNESS_AUTHORIZATION_TIMEOUT_MS);
209
+ const requested = timeoutMs ?? cap;
190
210
  if (!Number.isSafeInteger(requested) || requested < 1) {
191
211
  throw new Error("Access denied: invalid meeting corpus authorization timeout");
192
212
  }
193
- return process.hrtime.bigint() + BigInt(Math.min(requested, DEFAULT_AUTHORIZATION_TIMEOUT_MS)) * 1000000n;
213
+ return Math.min(requested, cap);
214
+ }
215
+ /** @internal Pure policy seam for test-harness gate regression coverage. */
216
+ export function resolveAuthorizationTimeoutMsForTest(timeoutMs, environment) {
217
+ return resolveAuthorizationTimeoutMs(timeoutMs, environment);
218
+ }
219
+ function authorizationDeadline(timeoutMs) {
220
+ return (process.hrtime.bigint() +
221
+ BigInt(resolveAuthorizationTimeoutMs(timeoutMs)) * 1000000n);
194
222
  }
195
223
  function remainingAuthorizationMs(deadline) {
196
224
  const remainingNs = deadline - process.hrtime.bigint();
@@ -1358,8 +1386,16 @@ function parentControls(commands, pauses) {
1358
1386
  * those name a caller-actionable limit rather than an authorization outcome.
1359
1387
  */
1360
1388
  export async function withStableCorpusLease(root, operation, hooks = {}) {
1389
+ const authorizationStarted = process.hrtime.bigint();
1361
1390
  try {
1362
- return await dispatchStableCorpusLease(root, operation, hooks);
1391
+ const result = await dispatchStableCorpusLease(root, operation, hooks);
1392
+ const durationMs = Number((process.hrtime.bigint() - authorizationStarted + 999999n) / 1000000n);
1393
+ // Match denial diagnostics: content-free, operator-visible, deferred, and
1394
+ // unable to turn an authorization result into an application failure.
1395
+ setImmediate(() => {
1396
+ writeOperatorDiagnostic(`[corpus-lease] authorized (authorization duration ${durationMs}ms)\n`);
1397
+ });
1398
+ return result;
1363
1399
  }
1364
1400
  catch (error) {
1365
1401
  if (error instanceof CorpusLeaseChangedError) {
package/dist/index.js CHANGED
@@ -1570,7 +1570,7 @@ const COPILOT_SUPPORTED = hasFeature(CLI_CAPABILITIES, "copilot_realtime");
1570
1570
  // `./version.ts` (see issue #183). Hosted `.mcpb` bundles will run
1571
1571
  // against CLIs with different minor/patch numbers within the same
1572
1572
  // major; that is explicitly supported.
1573
- const MCP_SERVER_VERSION = "0.25.4";
1573
+ const MCP_SERVER_VERSION = "0.25.6";
1574
1574
  export function parseKnowledgeConfig(configContent) {
1575
1575
  const knowledgeMatch = configContent.match(/\[knowledge\][\s\S]*?(?=\n\[|$)/);
1576
1576
  if (!knowledgeMatch) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minutes-mcp",
3
- "version": "0.25.4",
3
+ "version": "0.25.6",
4
4
  "description": "MCP server for minutes \u2014 conversation memory for AI assistants. Works with Claude Desktop, Mistral Vibe, Cursor, Windsurf, and any MCP client.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -32,20 +32,21 @@
32
32
  "scripts": {
33
33
  "build": "tsc && vite build",
34
34
  "build:ui": "vite build",
35
- "test": "npm run build && node test/mcp_tools_test.mjs && node test/copilot_mcp_contract.mjs && node test/mcp_http_transport_test.mjs && node test/surface_parity_test.mjs",
36
- "test:unit": "vitest run",
35
+ "test": "npm run build && node ../../scripts/run_corpus_test_harness.mjs npm run test:integration",
36
+ "test:integration": "node test/mcp_tools_test.mjs && node test/copilot_mcp_contract.mjs && node test/mcp_http_transport_test.mjs && node test/surface_parity_test.mjs",
37
+ "test:unit": "node ../../scripts/run_corpus_test_harness.mjs npx vitest run",
37
38
  "test:host-compat": "node test/live_events_host_compat.mjs",
38
39
  "test:copilot": "node test/copilot_mcp_contract.mjs",
39
40
  "test:http": "node test/mcp_http_transport_test.mjs",
40
41
  "test:surface-parity": "node test/surface_parity_test.mjs",
41
- "test:all": "vitest run && npm run build && node test/mcp_tools_test.mjs && node test/copilot_mcp_contract.mjs && node test/mcp_http_transport_test.mjs && node test/surface_parity_test.mjs",
42
+ "test:all": "npm run test:unit && npm test",
42
43
  "start": "node dist/index.js",
43
44
  "dev": "tsx src/index.ts"
44
45
  },
45
46
  "dependencies": {
46
47
  "@modelcontextprotocol/ext-apps": "^1.6.0",
47
48
  "@modelcontextprotocol/sdk": "^1.29.0",
48
- "minutes-sdk": "0.25.4",
49
+ "minutes-sdk": "0.25.6",
49
50
  "yaml": "^2.8.3",
50
51
  "zod": "^3.25 || ^4.0"
51
52
  },