neotoma 0.22.0 → 0.22.2
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/dist/actions.d.ts +13 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +236 -93
- package/dist/actions.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +11 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +90 -0
- package/dist/config.js.map +1 -1
- package/dist/docs/api/rest_api.md +81 -0
- package/dist/docs/developer/getting_started.md +45 -0
- package/dist/docs/developer/mcp/proxy.md +48 -28
- package/dist/docs/developer/npm_scripts.md +10 -4
- package/dist/docs/infrastructure/client_instance_deployment.md +50 -2
- package/dist/docs/operations/configuration.md +44 -1
- package/dist/docs/security/advisories/2026-08-26-jwt-bearer-unverified-fallback-auth-bypass.md +59 -0
- package/dist/docs/security/advisories/README.md +1 -0
- package/dist/docs/security/practices.md +5 -1
- package/dist/docs/subsystems/agent_session_architecture.md +69 -0
- package/dist/docs/subsystems/usage_digest.md +127 -0
- package/dist/docs/testing/automated_test_catalog.md +49 -26
- package/dist/docs/testing/testing_standard.md +1 -1
- package/dist/middleware/aauth_admission.js +1 -1
- package/dist/middleware/aauth_admission.js.map +1 -1
- package/dist/middleware/db_abort_context.d.ts +24 -0
- package/dist/middleware/db_abort_context.d.ts.map +1 -0
- package/dist/middleware/db_abort_context.js +41 -0
- package/dist/middleware/db_abort_context.js.map +1 -0
- package/dist/proxy/mcp_stdio_proxy.d.ts +134 -6
- package/dist/proxy/mcp_stdio_proxy.d.ts.map +1 -1
- package/dist/proxy/mcp_stdio_proxy.js +373 -17
- package/dist/proxy/mcp_stdio_proxy.js.map +1 -1
- package/dist/repositories/sqlite/local_db_adapter.d.ts.map +1 -1
- package/dist/repositories/sqlite/local_db_adapter.js +20 -0
- package/dist/repositories/sqlite/local_db_adapter.js.map +1 -1
- package/dist/repositories/sqlite/sqlite_client.d.ts.map +1 -1
- package/dist/repositories/sqlite/sqlite_client.js +10 -0
- package/dist/repositories/sqlite/sqlite_client.js.map +1 -1
- package/dist/repositories/worker/worker_file_database.d.ts +135 -1
- package/dist/repositories/worker/worker_file_database.d.ts.map +1 -1
- package/dist/repositories/worker/worker_file_database.js +726 -27
- package/dist/repositories/worker/worker_file_database.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +182 -77
- package/dist/server.js.map +1 -1
- package/dist/services/attachment_resolution.d.ts +149 -0
- package/dist/services/attachment_resolution.d.ts.map +1 -0
- package/dist/services/attachment_resolution.js +206 -0
- package/dist/services/attachment_resolution.js.map +1 -0
- package/dist/services/attachment_resolution_sqlite.d.ts +57 -0
- package/dist/services/attachment_resolution_sqlite.d.ts.map +1 -0
- package/dist/services/attachment_resolution_sqlite.js +75 -0
- package/dist/services/attachment_resolution_sqlite.js.map +1 -0
- package/dist/services/entity_queries.d.ts.map +1 -1
- package/dist/services/entity_queries.js +85 -23
- package/dist/services/entity_queries.js.map +1 -1
- package/dist/services/entity_snapshot_at_time.d.ts.map +1 -1
- package/dist/services/entity_snapshot_at_time.js +23 -3
- package/dist/services/entity_snapshot_at_time.js.map +1 -1
- package/dist/services/file_input_diagnostics.d.ts +89 -0
- package/dist/services/file_input_diagnostics.d.ts.map +1 -0
- package/dist/services/file_input_diagnostics.js +174 -0
- package/dist/services/file_input_diagnostics.js.map +1 -0
- package/dist/services/interpretation.d.ts.map +1 -1
- package/dist/services/interpretation.js +22 -8
- package/dist/services/interpretation.js.map +1 -1
- package/dist/services/mcp_auth.d.ts +19 -3
- package/dist/services/mcp_auth.d.ts.map +1 -1
- package/dist/services/mcp_auth.js +23 -33
- package/dist/services/mcp_auth.js.map +1 -1
- package/dist/services/mcp_oauth.d.ts +14 -1
- package/dist/services/mcp_oauth.d.ts.map +1 -1
- package/dist/services/mcp_oauth.js +86 -1
- package/dist/services/mcp_oauth.js.map +1 -1
- package/dist/services/raw_storage.d.ts.map +1 -1
- package/dist/services/raw_storage.js +14 -2
- package/dist/services/raw_storage.js.map +1 -1
- package/dist/services/readiness.d.ts +85 -0
- package/dist/services/readiness.d.ts.map +1 -0
- package/dist/services/readiness.js +93 -0
- package/dist/services/readiness.js.map +1 -0
- package/dist/services/route_shadowing.d.ts +67 -0
- package/dist/services/route_shadowing.d.ts.map +1 -0
- package/dist/services/route_shadowing.js +126 -0
- package/dist/services/route_shadowing.js.map +1 -0
- package/dist/services/schema_definitions.d.ts.map +1 -1
- package/dist/services/schema_definitions.js +171 -0
- package/dist/services/schema_definitions.js.map +1 -1
- package/dist/services/schema_lag_repair.d.ts.map +1 -1
- package/dist/services/schema_lag_repair.js +32 -12
- package/dist/services/schema_lag_repair.js.map +1 -1
- package/dist/services/schema_registry.d.ts.map +1 -1
- package/dist/services/schema_registry.js +12 -5
- package/dist/services/schema_registry.js.map +1 -1
- package/dist/services/snapshot_computation.d.ts.map +1 -1
- package/dist/services/snapshot_computation.js +12 -8
- package/dist/services/snapshot_computation.js.map +1 -1
- package/dist/services/subscriptions/sse_hub.d.ts.map +1 -1
- package/dist/services/subscriptions/sse_hub.js +19 -1
- package/dist/services/subscriptions/sse_hub.js.map +1 -1
- package/dist/shared/action_handlers/entity_handlers.d.ts.map +1 -1
- package/dist/shared/action_handlers/entity_handlers.js +110 -26
- package/dist/shared/action_handlers/entity_handlers.js.map +1 -1
- package/dist/shared/action_schemas.d.ts +6 -6
- package/dist/shared/contract_mappings.d.ts.map +1 -1
- package/dist/shared/contract_mappings.js +8 -1
- package/dist/shared/contract_mappings.js.map +1 -1
- package/dist/shared/openapi_types.d.ts +108 -3
- package/dist/shared/openapi_types.d.ts.map +1 -1
- package/dist/tool_definitions.d.ts.map +1 -1
- package/dist/tool_definitions.js +18 -13
- package/dist/tool_definitions.js.map +1 -1
- package/openapi.yaml +83 -3
- package/package.json +2 -1
- package/skills/status/SKILL.md +0 -1
- package/skills/where/SKILL.md +315 -0
package/dist/config.d.ts
CHANGED
|
@@ -24,6 +24,19 @@ export declare const config: {
|
|
|
24
24
|
/** When true, MCP clients receive the compact instruction block (same body as runtime fallback) instead of the full fenced block from docs — for dual-host setups that already load workspace Neotoma rules. */
|
|
25
25
|
mcpCompactInstructions: boolean;
|
|
26
26
|
oauthClientId: string;
|
|
27
|
+
/**
|
|
28
|
+
* Additional exact callback URLs an operator trusts to receive an authorization
|
|
29
|
+
* code when the authorize request arrives via a tunnel (non-local Host).
|
|
30
|
+
*
|
|
31
|
+
* Comma-separated list of FULL callback URLs, not origins — `https://app.example.com/auth/callback`
|
|
32
|
+
* authorises that path and nothing else on that host. Entries must be https: unless
|
|
33
|
+
* they point at a loopback host. Empty by default: an operator who sets nothing keeps
|
|
34
|
+
* exactly the behaviour they had before this existed.
|
|
35
|
+
*
|
|
36
|
+
* Validated at load, fail-closed on the WHOLE list: one malformed entry rejects
|
|
37
|
+
* every entry and fails startup. See parseTrustedCallbackUrls above for why.
|
|
38
|
+
*/
|
|
39
|
+
oauthTrustedCallbackUrls: string[];
|
|
27
40
|
requireKeyForOauth: boolean;
|
|
28
41
|
encryption: {
|
|
29
42
|
enabled: boolean;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAqQA,eAAO,MAAM,MAAM;;;;eAIO,QAAQ,GAAG,QAAQ;IAC3C,0FAA0F;;IAE1F,6DAA6D;;;;;;;;;;;;;;;;IA4B7D,gNAAgN;;;IAKhN;;;;;;;;;;;OAWG;;;;;;;;;;;;;;;;CAgCJ,CAAC;AAEF;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAsBpC"}
|
package/dist/config.js
CHANGED
|
@@ -164,6 +164,83 @@ const dbBackend = (process.env.NEOTOMA_DB_BACKEND || "sqlite").toLowerCase();
|
|
|
164
164
|
if (dbBackend !== "sqlite" && dbBackend !== "libsql") {
|
|
165
165
|
throw new Error(`Invalid NEOTOMA_DB_BACKEND "${process.env.NEOTOMA_DB_BACKEND}": expected "sqlite" or "libsql"`);
|
|
166
166
|
}
|
|
167
|
+
const OAUTH_CALLBACK_LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
168
|
+
/**
|
|
169
|
+
* Why an entry is refused, phrased for an operator reading a startup failure.
|
|
170
|
+
* Returns null when the entry is acceptable.
|
|
171
|
+
*/
|
|
172
|
+
function describeTrustedCallbackDefect(entry) {
|
|
173
|
+
let url;
|
|
174
|
+
try {
|
|
175
|
+
url = new URL(entry);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return "not a parseable absolute URL (a full URL with a scheme is required, e.g. https://app.example.com/auth/callback)";
|
|
179
|
+
}
|
|
180
|
+
const protocol = url.protocol.toLowerCase();
|
|
181
|
+
if (protocol !== "https:" && protocol !== "http:") {
|
|
182
|
+
return `scheme "${protocol}" is not supported here (use https:, or http: only for a loopback host)`;
|
|
183
|
+
}
|
|
184
|
+
if (url.username || url.password) {
|
|
185
|
+
return "carries userinfo (user:password@host), which is a URL-spoofing vector and is never load-bearing in a callback";
|
|
186
|
+
}
|
|
187
|
+
const host = url.hostname.toLowerCase();
|
|
188
|
+
if (!host) {
|
|
189
|
+
return "has no host";
|
|
190
|
+
}
|
|
191
|
+
if (protocol === "http:" && !OAUTH_CALLBACK_LOOPBACK_HOSTS.has(host)) {
|
|
192
|
+
return "is plaintext http: to a non-loopback host, which would ship authorization codes in cleartext (use https:)";
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Parse NEOTOMA_OAUTH_TRUSTED_CALLBACK_URLS, FAILING CLOSED on the whole list.
|
|
198
|
+
*
|
|
199
|
+
* If any entry is malformed, the entire list is rejected and startup fails —
|
|
200
|
+
* entries 1 and 3 do not survive a bad entry 2. This is deliberate and is the
|
|
201
|
+
* condition pre-registered on #2384 before implementation.
|
|
202
|
+
*
|
|
203
|
+
* The rejected alternative was skipping a bad entry and honouring the rest. That
|
|
204
|
+
* is friendlier on a typo, but it makes an allowlist enforce something other than
|
|
205
|
+
* what the operator wrote, with no signal that it did: the refusal a bad entry
|
|
206
|
+
* produces is indistinguishable from an exact-match miss. An allowlist is a
|
|
207
|
+
* security control, and a control that silently binds less than its configuration
|
|
208
|
+
* says is the failure mode in docs/foundation/principles.md#1. Refusing to start
|
|
209
|
+
* is loud, immediate, and happens before any authorization request is served,
|
|
210
|
+
* rather than surfacing as an unexplained sign-in failure weeks later.
|
|
211
|
+
*
|
|
212
|
+
* The blast radius of the strict reading is bounded: this throws only when the
|
|
213
|
+
* operator has actually set the variable. Leaving it unset is the default and is
|
|
214
|
+
* unaffected.
|
|
215
|
+
*/
|
|
216
|
+
function parseTrustedCallbackUrls(raw) {
|
|
217
|
+
const entries = (raw || "")
|
|
218
|
+
.split(",")
|
|
219
|
+
.map((entry) => entry.trim())
|
|
220
|
+
.filter((entry) => entry.length > 0);
|
|
221
|
+
const defects = entries
|
|
222
|
+
.map((entry, index) => {
|
|
223
|
+
const defect = describeTrustedCallbackDefect(entry);
|
|
224
|
+
// The entry is operator-authored config, not user input, and is already
|
|
225
|
+
// echoed in startup logs; but userinfo is the one part that could carry a
|
|
226
|
+
// credential, so redact it rather than printing it back.
|
|
227
|
+
return defect ? ` entry ${index + 1} ("${redactUrlUserinfo(entry)}"): ${defect}` : null;
|
|
228
|
+
})
|
|
229
|
+
.filter((defect) => defect !== null);
|
|
230
|
+
if (defects.length > 0) {
|
|
231
|
+
throw new Error(`Invalid NEOTOMA_OAUTH_TRUSTED_CALLBACK_URLS: ${defects.length} of ${entries.length} ` +
|
|
232
|
+
`entries are not usable as trusted OAuth callback URLs.\n${defects.join("\n")}\n` +
|
|
233
|
+
`The whole list is rejected rather than partially applied, so the allowlist in force ` +
|
|
234
|
+
`always matches what is configured. Fix the entries above, or unset the variable to ` +
|
|
235
|
+
`fall back to the built-in allowlist (localhost, loopback, cursor:/vscode:/app:, this ` +
|
|
236
|
+
`instance's own origin, and the ChatGPT/Claude callbacks).`);
|
|
237
|
+
}
|
|
238
|
+
return entries;
|
|
239
|
+
}
|
|
240
|
+
/** Replace any `user:password@` in a URL-ish string, for safe echoing in errors. */
|
|
241
|
+
function redactUrlUserinfo(value) {
|
|
242
|
+
return value.replace(/^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)[^/@]*@/, "$1<redacted>@");
|
|
243
|
+
}
|
|
167
244
|
export const config = {
|
|
168
245
|
projectRoot,
|
|
169
246
|
storageBackend,
|
|
@@ -196,6 +273,19 @@ export const config = {
|
|
|
196
273
|
mcpCompactInstructions: (process.env.NEOTOMA_MCP_COMPACT_INSTRUCTIONS || "").toLowerCase() === "1" ||
|
|
197
274
|
(process.env.NEOTOMA_MCP_COMPACT_INSTRUCTIONS || "").toLowerCase() === "true",
|
|
198
275
|
oauthClientId: process.env.NEOTOMA_OAUTH_CLIENT_ID || "",
|
|
276
|
+
/**
|
|
277
|
+
* Additional exact callback URLs an operator trusts to receive an authorization
|
|
278
|
+
* code when the authorize request arrives via a tunnel (non-local Host).
|
|
279
|
+
*
|
|
280
|
+
* Comma-separated list of FULL callback URLs, not origins — `https://app.example.com/auth/callback`
|
|
281
|
+
* authorises that path and nothing else on that host. Entries must be https: unless
|
|
282
|
+
* they point at a loopback host. Empty by default: an operator who sets nothing keeps
|
|
283
|
+
* exactly the behaviour they had before this existed.
|
|
284
|
+
*
|
|
285
|
+
* Validated at load, fail-closed on the WHOLE list: one malformed entry rejects
|
|
286
|
+
* every entry and fails startup. See parseTrustedCallbackUrls above for why.
|
|
287
|
+
*/
|
|
288
|
+
oauthTrustedCallbackUrls: parseTrustedCallbackUrls(process.env.NEOTOMA_OAUTH_TRUSTED_CALLBACK_URLS),
|
|
199
289
|
requireKeyForOauth: (process.env.NEOTOMA_REQUIRE_KEY_FOR_OAUTH || "true").toLowerCase() !== "false",
|
|
200
290
|
// Encryption settings (local backend)
|
|
201
291
|
encryption: {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -375,6 +375,87 @@ GET /health
|
|
|
375
375
|
|
|
376
376
|
**No authentication required.**
|
|
377
377
|
|
|
378
|
+
### Usage Statistics
|
|
379
|
+
|
|
380
|
+
Get aggregate usage statistics for the authenticated user. Powers the Neotoma Inspector dashboard summary tiles. Figures are computed on each request from live data — no server-side cache.
|
|
381
|
+
|
|
382
|
+
**Endpoint:** `GET /usage`
|
|
383
|
+
|
|
384
|
+
**Authentication:** Required — Bearer token, AAuth grant, or MCP OAuth token. Guest principals are rejected with `401`.
|
|
385
|
+
|
|
386
|
+
**Query parameters:**
|
|
387
|
+
|
|
388
|
+
| Parameter | Type | Required | Description |
|
|
389
|
+
| --------- | ----------- | -------- | -------------------------------------------------------------------------------------- |
|
|
390
|
+
| `user_id` | UUID string | No | Must match authenticated user if supplied. AAuth-admitted agents cannot override this. |
|
|
391
|
+
|
|
392
|
+
**Request:**
|
|
393
|
+
|
|
394
|
+
```http
|
|
395
|
+
GET /usage HTTP/1.1
|
|
396
|
+
Authorization: Bearer <NEOTOMA_BEARER_TOKEN>
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
**curl example:**
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
curl -s \
|
|
403
|
+
-H "Authorization: Bearer $NEOTOMA_BEARER_TOKEN" \
|
|
404
|
+
http://localhost:3080/usage | jq .
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**Response:** `200 OK`
|
|
408
|
+
|
|
409
|
+
```json
|
|
410
|
+
{
|
|
411
|
+
"entities_by_type": {
|
|
412
|
+
"conversation": 214,
|
|
413
|
+
"task": 156,
|
|
414
|
+
"contact": 88
|
|
415
|
+
},
|
|
416
|
+
"total_entities": 500,
|
|
417
|
+
"observations_by_source": {
|
|
418
|
+
"human": 310,
|
|
419
|
+
"llm_summary": 140,
|
|
420
|
+
"sensor": 50
|
|
421
|
+
},
|
|
422
|
+
"total_observations": 500,
|
|
423
|
+
"entities_created_last_7_days": 34,
|
|
424
|
+
"entities_created_last_30_days": 112,
|
|
425
|
+
"entity_types_with_schema": 6,
|
|
426
|
+
"entity_types_total": 10,
|
|
427
|
+
"last_updated": "2026-06-19T09:00:00.000Z"
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**Response fields:**
|
|
432
|
+
|
|
433
|
+
| Field | Type | Description |
|
|
434
|
+
| ------------------------------- | ------------------------ | --------------------------------------------------------------------------------------------- |
|
|
435
|
+
| `entities_by_type` | `Record<string, number>` | Active entity counts per type, sorted by count descending. |
|
|
436
|
+
| `total_entities` | `number` | Total active (non-merged) entities. |
|
|
437
|
+
| `observations_by_source` | `Record<string, number>` | Observation counts per `observation_source`; unsourced rows appear as `"unclassified"`. |
|
|
438
|
+
| `total_observations` | `number` | Total observations. |
|
|
439
|
+
| `entities_created_last_7_days` | `number` | Entities created within the last 7 days. |
|
|
440
|
+
| `entities_created_last_30_days` | `number` | Entities created within the last 30 days. |
|
|
441
|
+
| `entity_types_with_schema` | `number` | Distinct entity types present in the data that also have an active registered schema. |
|
|
442
|
+
| `entity_types_total` | `number` | Total distinct entity types present across all active entities. |
|
|
443
|
+
| `last_updated` | `string` (ISO-8601) | Timestamp when these aggregates were computed (reflects request time, not a cache watermark). |
|
|
444
|
+
|
|
445
|
+
**Error responses:**
|
|
446
|
+
|
|
447
|
+
| Status | `error_code` | Cause |
|
|
448
|
+
| ------ | ----------------- | -------------------------------------------------------- |
|
|
449
|
+
| `401` | `AUTH_REQUIRED` | Missing or invalid token; guest principal. |
|
|
450
|
+
| `403` | `FORBIDDEN` | `user_id` query param does not match authenticated user. |
|
|
451
|
+
| `500` | `DB_QUERY_FAILED` | Database query failure. |
|
|
452
|
+
|
|
453
|
+
**OpenAPI:** `operationId: getUsage` — see `openapi.yaml` and `src/shared/openapi_types.ts` (`UsageStats` schema).
|
|
454
|
+
|
|
455
|
+
**CLI equivalent:** `neotoma request --operation getUsage`
|
|
456
|
+
|
|
457
|
+
**See also:** [`docs/subsystems/usage_digest.md`](../subsystems/usage_digest.md#usage-http-api-endpoint) for the full endpoint reference including the distinction between `/usage` HTTP aggregates and `usage_digest` telemetry entities.
|
|
458
|
+
|
|
378
459
|
### OpenAPI Specification
|
|
379
460
|
|
|
380
461
|
Get OpenAPI spec for API documentation.
|
|
@@ -118,6 +118,51 @@ npm run type-check
|
|
|
118
118
|
npm run lint
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
`npm test` runs the whole Vitest suite, which is wider than the CI baseline lane
|
|
122
|
+
(that lane runs `npm run test:unit`). The extra lanes — `tests/integration`,
|
|
123
|
+
`tests/fixtures` and `inspector/src` — reach build artifacts a plain `npm ci`
|
|
124
|
+
does not produce: the built Inspector SPA at `dist/inspector`, the Inspector's
|
|
125
|
+
own `inspector/node_modules`, and the compiled `packages/cursor-hooks/dist`.
|
|
126
|
+
|
|
127
|
+
### Local prerequisites and the skip policy
|
|
128
|
+
|
|
129
|
+
On a fresh clone those artifacts are absent, and the suites that need them
|
|
130
|
+
**skip with a named reason** rather than fail. The reason is printed at the top
|
|
131
|
+
of the run:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
[neotoma] SKIP inspector-shell suites — missing prerequisite: built inspector assets — npm run build:inspector (or npm run test:setup)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
So `npm test` and the pre-commit hook both pass on a fresh clone with no extra
|
|
138
|
+
setup, and any failure you see is attributable to your own change. This is
|
|
139
|
+
deliberate: a failure caused by a missing local build step is indistinguishable
|
|
140
|
+
from a real regression, and that ambiguity is what drove contributors to
|
|
141
|
+
`--no-verify`.
|
|
142
|
+
|
|
143
|
+
To actually **run** the skipped suites — do this before trusting a green run on
|
|
144
|
+
a change that touches the Inspector or the cursor hooks — install and build
|
|
145
|
+
their prerequisites once per checkout:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm run test:setup
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Skips are opt-out by construction: the moment the artifact exists the suite runs
|
|
152
|
+
again, with no flag to remember.
|
|
153
|
+
|
|
154
|
+
### If `dist/` is missing
|
|
155
|
+
|
|
156
|
+
`npm test` builds the server first via `pretest`, so this only bites when you
|
|
157
|
+
invoke Vitest directly. A raw `npx vitest run` on an unbuilt checkout stops
|
|
158
|
+
immediately with:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
[neotoma] dist/ is missing. Run `npm test` (pretest builds server) or `npm run build:server` before `npx vitest run`.
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
rather than emitting hundreds of unrelated failures across `tests/cli/**`.
|
|
165
|
+
|
|
121
166
|
## Feature guides
|
|
122
167
|
|
|
123
168
|
- [Plans](plans_guide.md) — store engineering plans as entities, with optional disk mirror.
|
|
@@ -8,27 +8,27 @@ Canonical Cursor wiring, screenshots, and transport choice live in **[`mcp_curso
|
|
|
8
8
|
|
|
9
9
|
Stable **`mcp.json` `command` paths** stay at the repo-root `scripts/` filenames below (no subdirectory indirection). Optional relocation under e.g. `scripts/mcp_launchers/` with thin forwarders was deferred to avoid churn for operators who hardcode absolute paths. Shared behavior lives in **`scripts/lib/neotoma_mcp_source_env.sh`** (`.env.dev` → `.env` → `.env.development`, first file found) and **`scripts/lib/neotoma_mcp_resolve_downstream_url.sh`** (port-file + TCP probe for `MCP_PROXY_DOWNSTREAM_URL`, used by both HTTP proxy shims).
|
|
10
10
|
|
|
11
|
-
| Script
|
|
12
|
-
|
|
13
|
-
| `run_neotoma_mcp_stdio.sh`
|
|
14
|
-
| `run_neotoma_mcp_stdio_dev_watch.sh`
|
|
15
|
-
| `run_neotoma_mcp_stdio_prod.sh`
|
|
16
|
-
| `run_neotoma_mcp_stdio_prod_watch.sh`
|
|
17
|
-
| `run_neotoma_mcp_stdio_dev_shim.sh`
|
|
18
|
-
| `run_neotoma_mcp_signed_stdio_dev_shim.sh`
|
|
19
|
-
| `run_neotoma_mcp_unsigned_stdio_dev_shim.sh` | stdio → **`mcp proxy`** (no forced AAuth) | `neotoma mcp proxy`
|
|
20
|
-
| `run_neotoma_mcp_unsigned_stdio_proxy.sh`
|
|
11
|
+
| Script | Transport | Signing / worker | Reload | Default downstream / entry | Env files (via lib) |
|
|
12
|
+
| -------------------------------------------- | ----------------------------------------- | ---------------------------------------------- | ------------------------------------------------ | -------------------------------------------------- | -------------------------------------- |
|
|
13
|
+
| `run_neotoma_mcp_stdio.sh` | stdio → in-process MCP | None (`dist/index.js` or `tsx src/index.ts`) | Manual reconnect after code change | n/a | `.env.dev`, `.env`, `.env.development` |
|
|
14
|
+
| `run_neotoma_mcp_stdio_dev_watch.sh` | stdio → `tsx watch src/index.ts` | None | `tsx watch` (stdout risk; not for installed MCP) | n/a | same |
|
|
15
|
+
| `run_neotoma_mcp_stdio_prod.sh` | stdio → in-process MCP | None; **`NEOTOMA_ENV=production`** | Manual | n/a | same |
|
|
16
|
+
| `run_neotoma_mcp_stdio_prod_watch.sh` | stdio → plain `tsx src/index.ts` | None; prod env | Manual (comment warns: no `watch` on stdio) | n/a | same |
|
|
17
|
+
| `run_neotoma_mcp_stdio_dev_shim.sh` | stdio → **`mcp_dev_shim`** | Worker default in-process MCP | Shim restarts worker on file change | n/a | same |
|
|
18
|
+
| `run_neotoma_mcp_signed_stdio_dev_shim.sh` | stdio → shim → **HTTP `/mcp`** | **`mcp proxy --aauth`** (AAuth) | Shim + worker reload | `http://127.0.0.1:3080/mcp` unless port file / env | same |
|
|
19
|
+
| `run_neotoma_mcp_unsigned_stdio_dev_shim.sh` | stdio → **`mcp proxy`** (no forced AAuth) | `neotoma mcp proxy` | No shim watch (restart MCP to pick up code) | `http://127.0.0.1:3080/mcp` unless port file / env | same |
|
|
20
|
+
| `run_neotoma_mcp_unsigned_stdio_proxy.sh` | same as unsigned shim | Deprecated forwarder: **`exec`** unsigned shim | same | same | n/a |
|
|
21
21
|
|
|
22
22
|
## Downstream URL and signing
|
|
23
23
|
|
|
24
|
-
| Variable
|
|
25
|
-
|
|
26
|
-
| `MCP_PROXY_DOWNSTREAM_URL`
|
|
27
|
-
| `MCP_PROXY_AAUTH`
|
|
28
|
-
| `MCP_PROXY_CLIENT_NAME`, `MCP_PROXY_CLIENT_VERSION`, `MCP_PROXY_AGENT_LABEL`
|
|
29
|
-
| `MCP_PROXY_BEARER_TOKEN`, `MCP_PROXY_CONNECTION_ID`
|
|
30
|
-
| `MCP_PROXY_SESSION_PREFLIGHT`, `MCP_PROXY_SESSION_PREFLIGHT_BASE`, `MCP_PROXY_FAIL_CLOSED` | Trust / preflight behavior. See `src/cli/mcp_proxy.ts` and `src/proxy/mcp_stdio_proxy.ts`.
|
|
31
|
-
| `NEOTOMA_AAUTH_AUTHORITY_OVERRIDE`
|
|
24
|
+
| Variable | Default / notes |
|
|
25
|
+
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
26
|
+
| `MCP_PROXY_DOWNSTREAM_URL` | `http://127.0.0.1:3080/mcp` when unset (override per environment). |
|
|
27
|
+
| `MCP_PROXY_AAUTH` | When truthy, load `~/.neotoma/aauth/` keys and sign requests (`neotoma mcp proxy --aauth`). |
|
|
28
|
+
| `MCP_PROXY_CLIENT_NAME`, `MCP_PROXY_CLIENT_VERSION`, `MCP_PROXY_AGENT_LABEL` | Self-report for `clientInfo` injection. |
|
|
29
|
+
| `MCP_PROXY_BEARER_TOKEN`, `MCP_PROXY_CONNECTION_ID` | Optional auth headers. |
|
|
30
|
+
| `MCP_PROXY_SESSION_PREFLIGHT`, `MCP_PROXY_SESSION_PREFLIGHT_BASE`, `MCP_PROXY_FAIL_CLOSED` | Trust / preflight behavior. See `src/cli/mcp_proxy.ts` and `src/proxy/mcp_stdio_proxy.ts`. |
|
|
31
|
+
| `NEOTOMA_AAUTH_AUTHORITY_OVERRIDE` | Canonical host for signing when downstream uses `127.0.0.1` (often `localhost:<port>`). The signed **stdio shim** script can derive this from `MCP_PROXY_DOWNSTREAM_URL` when unset. |
|
|
32
32
|
|
|
33
33
|
> **Operator security note:** Hosted and operator-managed deployments should set **`MCP_PROXY_FAIL_CLOSED=1`** (or the equivalent `failClosed: true` proxy option) whenever AAuth signing is required. This prevents the proxy from forwarding unsigned downstream requests if signing or session preflight fails.
|
|
34
34
|
|
|
@@ -57,11 +57,11 @@ When **`NEOTOMA_MCP_USE_LOCAL_PORT_FILE=1`** (or `true`) is set in **`mcp.json`
|
|
|
57
57
|
|
|
58
58
|
**Verification:** on MCP spawn, stderr should show `[neotoma-mcp-signed-shim]` or `[neotoma-mcp-unsigned-stdio-dev-shim]` for port-file resolution lines, then `[neotoma-mcp-proxy] Starting proxy: downstream=…`.
|
|
59
59
|
|
|
60
|
-
| Variable
|
|
61
|
-
|
|
62
|
-
| `NEOTOMA_MCP_USE_LOCAL_PORT_FILE`
|
|
60
|
+
| Variable | Purpose |
|
|
61
|
+
| ------------------------------------- | ------------------------------------------------------------------------------- |
|
|
62
|
+
| `NEOTOMA_MCP_USE_LOCAL_PORT_FILE` | `1` / `true` → resolve downstream URL from port files + TCP probe. |
|
|
63
63
|
| `NEOTOMA_MCP_LOCAL_HTTP_PORT_PROFILE` | `dev` or `prod` — which port file(s) to read (preset A sets this per MCP slot). |
|
|
64
|
-
| `NEOTOMA_MCP_PORT_PROBE_MS`
|
|
64
|
+
| `NEOTOMA_MCP_PORT_PROBE_MS` | TCP probe timeout in ms (default `1200`, max `5000`). |
|
|
65
65
|
|
|
66
66
|
**CLI parity:** When the same env vars are set in the shell (not only in `mcp.json`), the **`neotoma` CLI** `resolveBaseUrl()` path uses the same profile rules and TCP probe after session port env and before `config.json` `base_url`, returning `http://localhost:<port>` so AAuth authority matches the API (for example `neotoma inspector admin unlock`). Profile follows **`NEOTOMA_MCP_LOCAL_HTTP_PORT_PROFILE`** if set, else **`NEOTOMA_ENV`**. Project root: `NEOTOMA_PROJECT_ROOT`, then `project_root` / `repo_root` in `~/.config/neotoma/config.json`, else `cwd`.
|
|
67
67
|
|
|
@@ -75,15 +75,35 @@ Streamable HTTP MCP keeps each session in **process memory** (`mcpTransports` in
|
|
|
75
75
|
|
|
76
76
|
As of neotoma#1923, an unknown/expired session returns **404** (not 503), per the [MCP Streamable HTTP session management spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#session-management) — this lets spec-compliant clients auto-reinitialize instead of treating the server as unavailable. Servers predating that fix return 503 for the same condition; `neotoma mcp proxy` recognizes both.
|
|
77
77
|
|
|
78
|
-
| Symptom
|
|
79
|
-
|
|
80
|
-
| **400** — no session header on a non-`initialize` POST
|
|
81
|
-
| **404** (or, against an older server, **503**) — session header present but unknown on this instance
|
|
82
|
-
| **404** (or **503**) — same, while using **`neotoma mcp proxy`**
|
|
83
|
-
| **404** / **503** / **400** after deploy or restart
|
|
78
|
+
| Symptom | Typical cause | What to do |
|
|
79
|
+
| ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
80
|
+
| **400** — no session header on a non-`initialize` POST | Proxy never stored an id (failed init, stripped response header) or client skipped `initialize` | Restart the MCP server in the IDE; confirm proxy stderr shows a successful downstream `initialize` and that your reverse proxy **forwards** `mcp-session-id` on responses and requests (custom headers are not hop-by-hop but some templates hide unknown headers). |
|
|
81
|
+
| **404** (or, against an older server, **503**) — session header present but unknown on this instance | **Load-balanced replicas** without affinity: `initialize` hit instance A, `tools/call` hit B | Use **sticky sessions** for `POST /mcp` (same as [`/mcp/oauth`](../subsystems/auth.md) guidance), scale MCP to **one** API replica for `/mcp`, or terminate TLS on a single Node process. |
|
|
82
|
+
| **404** (or **503**) — same, while using **`neotoma mcp proxy`** | Transient replica drift or API restart after the IDE finished `initialize` | The proxy **replays `initialize` to downstream once** (without emitting a second `initialize` on stdout), captures a fresh `mcp-session-id`, and **retries the failing RPC once**. If the second attempt still fails, fix infra (sticky sessions / single `/mcp` worker) or restart the MCP client. |
|
|
83
|
+
| **404** / **503** / **400** after deploy or restart | In-memory map cleared | Restart the MCP client once so `initialize` runs again. |
|
|
84
|
+
| `handshake_unreachable` — the first `initialize` never reached a server (CONNECT_TIMEOUT, ECONNREFUSED, socket closed) | Backend down, restarting, or the wrong `--downstream-url` | The proxy already retried with backoff (neotoma#2321) and the backend stayed unreachable for the whole window. Check `/health` and the downstream URL, then restart the MCP client once the backend answers. |
|
|
85
|
+
| `handshake_server_error` — the first `initialize` reached the server, which failed internally (5xx, or `-32603` through a 200) | Substrate crash surfacing through the handshake (e.g. neotoma#2316's "DB request aborted by caller") | Also already retried. The server is broken rather than refusing you: check server logs and `/health`, redeploy if needed, then restart the MCP client. |
|
|
86
|
+
| `handshake_auth_rejected` — the first `initialize` was refused for authentication (401) | Invalid/expired bearer, encryption-mode token required, unauthenticated POST, or invalid `X-Connection-Id` | **Not retried, deliberately** — a replay cannot fix a credential. Fix the credential: re-run `neotoma auth mcp-token`, or remove `Authorization` / `X-Connection-Id` from `mcp.json` and reconnect. |
|
|
87
|
+
| Tools appear missing / the agent answers about the graph "from silence" | An exhausted handshake leaves a session with no tools | An exhausted handshake is a **connection failure, not a missing tool** — its error says so explicitly (`NOT a missing tool`). Check proxy stderr for `initialize exhausted` before concluding a tool does not exist. |
|
|
84
88
|
|
|
85
89
|
When debugging, read the proxy line `Downstream error status=… body=…` (stderr): the JSON body includes the real `message` from Neotoma or the MCP SDK.
|
|
86
90
|
|
|
91
|
+
### Handshake retry (neotoma#2321)
|
|
92
|
+
|
|
93
|
+
Session-loss recovery cannot help an `initialize` that never succeeded — there is no session to recover and no cached handshake to replay — so a failed handshake used to be permanent for the life of the client. Every session opened during an outage stayed dark long after the backend recovered, while sessions already established were fine.
|
|
94
|
+
|
|
95
|
+
The proxy now retries the handshake, but only on a failure a replay can fix: a transport failure that never reached a server, or a server that answered with its own internal error. An `initialize` refused for **authentication is never retried**, because retrying would hammer a server that is correctly rejecting a credential and mask the real cause.
|
|
96
|
+
|
|
97
|
+
Retries are bounded twice over: by `NEOTOMA_MCP_PROXY_MAX_ATTEMPTS` (default 4) and by a wall-clock budget, `NEOTOMA_MCP_PROXY_HANDSHAKE_BUDGET_MS` (default 45s). The wall-clock bound matters because the proxy emits nothing until it resolves, so the client sits blocked on its own `initialize` timeout — 60s by default in the MCP SDK — for the whole retry window. Overrunning that would turn a recoverable handshake into a client-side abort.
|
|
98
|
+
|
|
99
|
+
A recovered handshake looks like this on stderr — note the client never sees the intermediate failures, only the successful `initialize`:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
[neotoma-mcp-proxy] initialize retry attempt=1/4 (retryable_transport): fetch failed cause=ECONNREFUSED — retrying
|
|
103
|
+
[neotoma-mcp-proxy] initialize retry attempt=2/4 (retryable_server): downstream status=500 — retrying
|
|
104
|
+
[neotoma-mcp-proxy] initialize recovered after 3 attempts
|
|
105
|
+
```
|
|
106
|
+
|
|
87
107
|
## Related
|
|
88
108
|
|
|
89
109
|
- [`mcp_cursor_setup.md`](../mcp_cursor_setup.md) — Cursor `mcp.json` examples, signed shim, port file JSON.
|
|
@@ -102,14 +102,20 @@ Keep these aliases for one minor release, update docs and automation to the cano
|
|
|
102
102
|
|
|
103
103
|
## Generated files
|
|
104
104
|
|
|
105
|
-
Some committed files are generated from source and must be kept in sync. Run the generator after making the relevant source change
|
|
105
|
+
Some committed files are generated from source and must be kept in sync. Run the generator after making the relevant source change. CI policy differs by artifact: a pure tree inventory is re-rendered; contract/registration derivatives still fail on drift.
|
|
106
106
|
|
|
107
107
|
| Script | What it does | When to run | CI usage |
|
|
108
108
|
|--------|-------------|-------------|----------|
|
|
109
|
-
| `generate:test-catalog` | Regenerates `docs/testing/automated_test_catalog.md` from the test tree | After adding, removing, or renaming a test file | `npm run
|
|
110
|
-
| `validate:test-catalog` | Checks that `docs/testing/automated_test_catalog.md` matches the current test tree |
|
|
109
|
+
| `generate:test-catalog` | Regenerates `docs/testing/automated_test_catalog.md` from the test tree | After adding, removing, or renaming a test file | Baseline lane runs `npm run generate:test-catalog` (render; does not fail on pre-existing staleness) |
|
|
110
|
+
| `validate:test-catalog` | Checks that `docs/testing/automated_test_catalog.md` matches the current test tree | Locally, before opening a PR | Advisory. Not used in CI — the baseline lane runs `generate:test-catalog` instead |
|
|
111
111
|
| `generate:capability-manifest` | Regenerates `src/shared/capability_manifest.json` by walking git `vX.Y.Z` release tags and recording first/last appearance of each MCP tool in `src/tool_definitions.ts` | After adding or removing an MCP tool, or after cutting a new release tag | `npm run validate:capability-manifest` (fails on drift) |
|
|
112
|
-
| `validate:capability-manifest` | Checks that `src/shared/capability_manifest.json` matches what the generator would produce | Before every merge | Runs in CI alongside `
|
|
112
|
+
| `validate:capability-manifest` | Checks that `src/shared/capability_manifest.json` matches what the generator would produce | Before every merge | Runs in CI alongside `generate:test-catalog` |
|
|
113
|
+
|
|
114
|
+
Sibling artifacts that look similar but are intentionally different:
|
|
115
|
+
|
|
116
|
+
- `openapi.yaml` is an **authored** API contract (not generated). Do not treat staleness of a generated catalog as a reason to auto-rewrite it.
|
|
117
|
+
- `src/shared/openapi_types.ts` is derived from authored `openapi.yaml`. CI regenerates then **fails on `git diff`** — drift means the YAML changed without committing types, which is registration/contract drift, not a pure inventory refresh.
|
|
118
|
+
- `src/shared/capability_manifest.json` stays **fail-on-drift** (`validate:capability-manifest`) because a missed regen is tool/release registration drift, not a filename inventory refresh.
|
|
113
119
|
|
|
114
120
|
## Validation
|
|
115
121
|
|
|
@@ -27,8 +27,12 @@ Fly config from the repo; do not reintroduce it.
|
|
|
27
27
|
git worktree add ~/repos/neotoma-deploy origin/main
|
|
28
28
|
cd ~/repos/neotoma-deploy
|
|
29
29
|
|
|
30
|
+
# ALWAYS check drift first. This is not optional — see rule 0 below.
|
|
31
|
+
scripts/check_fly_config_drift.sh --app "$CLIENT_FLY_APP" -c fly.operator.toml
|
|
32
|
+
|
|
30
33
|
flyctl deploy \
|
|
31
34
|
--app "$CLIENT_FLY_APP" \
|
|
35
|
+
-c fly.operator.toml \
|
|
32
36
|
--build-arg VITE_NEOTOMA_SANDBOX_UI="" \
|
|
33
37
|
--build-arg VITE_PUBLIC_BASE_PATH="/" \
|
|
34
38
|
--no-cache
|
|
@@ -36,6 +40,41 @@ flyctl deploy \
|
|
|
36
40
|
|
|
37
41
|
Everything below explains why each of those pieces is load-bearing.
|
|
38
42
|
|
|
43
|
+
### 0. Check for config drift before every deploy
|
|
44
|
+
|
|
45
|
+
`flyctl deploy` reapplies the committed `[[vm]]` and `[http_service]` blocks
|
|
46
|
+
over the running machine. It does **not** merge, and it prints **no warning
|
|
47
|
+
when it shrinks one**. Whatever the config in your checkout says is what the
|
|
48
|
+
machine becomes.
|
|
49
|
+
|
|
50
|
+
On 2026-09-01 a deploy run from a checkout **139 commits behind main**
|
|
51
|
+
reapplied that checkout's `1gb` / `shared-cpu-1x` guest over an instance
|
|
52
|
+
running `performance` / 2 CPU / 8GB, and dropped its health check. The instance
|
|
53
|
+
went from slow to unreachable for roughly 30 minutes. Throughout, `flyctl
|
|
54
|
+
status` reported `started`, `flyctl machine restart` printed "No health checks
|
|
55
|
+
found", and the `CHECKS` column was empty — nothing anywhere reported a
|
|
56
|
+
problem. It was noticed only because an agent failed to write.
|
|
57
|
+
|
|
58
|
+
Two lessons, both mechanical rather than a matter of care:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# 1. Deploy from a checkout that is actually current.
|
|
62
|
+
git -C ~/repos/neotoma-deploy fetch origin && \
|
|
63
|
+
git -C ~/repos/neotoma-deploy status -sb # must show no "behind"
|
|
64
|
+
|
|
65
|
+
# 2. Compare the config against the live machine before applying it.
|
|
66
|
+
scripts/check_fly_config_drift.sh --app "$CLIENT_FLY_APP" -c fly.operator.toml
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Exit 0 means the deploy will not resize the machine or drop its checks. Exit 1
|
|
70
|
+
means it would — resolve that before deploying. Exit 2 means the check could
|
|
71
|
+
not run (no `flyctl`, no `jq`, app unreachable); treat that as unknown, never
|
|
72
|
+
as "fine".
|
|
73
|
+
|
|
74
|
+
**A machine scaled up by hand will be reverted by the next deploy.** If an
|
|
75
|
+
instance was resized to address load, that new size has to be written into the
|
|
76
|
+
config it deploys from, or it lasts exactly until the next release.
|
|
77
|
+
|
|
39
78
|
## The five load-bearing rules
|
|
40
79
|
|
|
41
80
|
### 1. Deploy from `main`, not a feature branch
|
|
@@ -48,11 +87,20 @@ a repeated source of breakage. Deploy from a clean `origin/main` checkout.
|
|
|
48
87
|
|
|
49
88
|
### 2. Pass `--app <name>` explicitly — do NOT rely on `-c fly.toml`
|
|
50
89
|
|
|
51
|
-
|
|
52
|
-
|
|
90
|
+
`fly.toml` deliberately declares **no** `app` key (#2013), so a bare `flyctl
|
|
91
|
+
deploy` fails with "the config for your app is missing an app name" rather than
|
|
92
|
+
succeeding against whichever app the file happens to name. It previously said
|
|
93
|
+
`app = 'neotoma-sandbox'`, and a deploy meant for a client instance would
|
|
94
|
+
silently retarget the sandbox and report success.
|
|
95
|
+
|
|
53
96
|
Always pass `--app "$CLIENT_FLY_APP"` explicitly. Read the app name from the
|
|
54
97
|
operator binding (below), never hardcode it here.
|
|
55
98
|
|
|
99
|
+
Note what `--app` does and does not override: it changes the deploy **target**
|
|
100
|
+
only. The `[[vm]]` and `[http_service]` blocks in whichever config is loaded
|
|
101
|
+
still apply to that target — which is why rule 0's drift check matters even
|
|
102
|
+
when the app name is correct.
|
|
103
|
+
|
|
56
104
|
### 3. Never use `fly.sandbox.toml` for a client instance
|
|
57
105
|
|
|
58
106
|
`fly.sandbox.toml` is for the public sandbox only. It sets:
|
|
@@ -32,7 +32,8 @@ Resolution order for the data directory and variables: a project-local `.env`, t
|
|
|
32
32
|
| `NEOTOMA_DB_BACKEND` | DB driver: `sqlite` (synchronous, zero-config) or `libsql` (concurrent — statements run off the event loop via worker-hosted driver for local files, or @libsql/client for remote sqld/Turso, so slow queries can't freeze the server; recommended for hosted/agent-heavy/shared instances) | `sqlite` |
|
|
33
33
|
| `NEOTOMA_DB_URL` | libsql connection URL (`file:` for embedded local, `http(s)://`/`libsql://` for remote sqld/Turso) | `file:{NEOTOMA_SQLITE_PATH}` |
|
|
34
34
|
| `NEOTOMA_DB_AUTH_TOKEN` | Auth token for remote libsql connections | unset |
|
|
35
|
-
| `NEOTOMA_DB_READER_WORKERS` | Read-only worker connections for the local `libsql` backend (WAL lets them run concurrently with the writer) | `2` |
|
|
35
|
+
| `NEOTOMA_DB_READER_WORKERS` | Read-only worker connections for the local `libsql` backend (WAL lets them run concurrently with the writer). Reads go to the least-loaded reader, so raising this adds capacity rather than just slots | `2` |
|
|
36
|
+
| `NEOTOMA_DB_STATEMENT_TIMEOUT_MS` | Per-statement budget for reads on that reader pool. On expiry the reader is terminated (the synchronous driver cannot be interrupted mid-statement) and respawns on the next read, so one runaway query cannot hold a pool slot indefinitely. Writes and statements inside a transaction are never timed out. `0` disables | `30000` |
|
|
36
37
|
| `NEOTOMA_RAW_STORAGE_DIR` | Content-addressed source files | `{dataDir}/sources` |
|
|
37
38
|
| `NEOTOMA_LOGS_DIR` / `NEOTOMA_EVENT_LOG_PATH` | Log directory and event log file | under `{dataDir}/logs` |
|
|
38
39
|
| `NEOTOMA_HOST_URL` / `NEOTOMA_PUBLIC_BASE_URL` | Public URL of this instance | auto-discovered or unset |
|
|
@@ -61,9 +62,51 @@ See [Running the Server](running_the_server.md) for transports and processes.
|
|
|
61
62
|
| --- | --- |
|
|
62
63
|
| `NEOTOMA_REQUIRE_KEY_FOR_OAUTH` | Require a key for OAuth connections |
|
|
63
64
|
| `NEOTOMA_OAUTH_CLIENT_ID` | MCP OAuth client id (hosted mode) |
|
|
65
|
+
| `NEOTOMA_OAUTH_TRUSTED_CALLBACK_URLS` | Comma-separated **exact** callback URLs additionally trusted to receive an authorization code when the authorize request arrives via a tunnel. Empty by default. See below. |
|
|
64
66
|
| `NEOTOMA_SANDBOX_MODE` | Opt into the public hosted-sandbox profile |
|
|
65
67
|
| `NEOTOMA_REFUSE_MODE` | `warn` or `enforce` when a no-auth, non-loopback topology is detected |
|
|
66
68
|
|
|
69
|
+
### Trusted OAuth callback URLs
|
|
70
|
+
|
|
71
|
+
When an authorize request reaches a local-backend instance over a tunnel, the `redirect_uri` must be on an allowlist, so an authorization code is never handed to a third-party site. Built in are the `cursor:`/`vscode:`/`app:` schemes, localhost and loopback, this instance's own origin, and the ChatGPT and Claude callbacks.
|
|
72
|
+
|
|
73
|
+
To let a **self-hosted first-party app** complete sign-in against a hosted instance, set its callback URL:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
NEOTOMA_OAUTH_TRUSTED_CALLBACK_URLS=https://app.example.com/auth/callback
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Several entries are comma-separated. Rules worth knowing before you set it:
|
|
80
|
+
|
|
81
|
+
- **Exact full URLs, not origins.** The example above authorises `https://app.example.com/auth/callback` and **not** `https://app.example.com/anything-else`. Configure every callback path you need.
|
|
82
|
+
- **https only**, unless the host is loopback. A plaintext `http://` entry to any other host is rejected rather than honoured.
|
|
83
|
+
- **A bad entry rejects the whole list, and the server will not start.** See below.
|
|
84
|
+
|
|
85
|
+
#### What the server compares
|
|
86
|
+
|
|
87
|
+
A redirect is accepted when the request's callback and a configured entry agree on **scheme, host, port and path** — all four. In detail:
|
|
88
|
+
|
|
89
|
+
| Part | How it is compared |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| Scheme | Must match. `https` does not authorise its `http` twin. |
|
|
92
|
+
| Host | Case-**insensitive**. `APP.EXAMPLE.COM` matches `app.example.com`. |
|
|
93
|
+
| Port | Must match, but a default port is equivalent to none: `https://app.example.com` = `https://app.example.com:443`. |
|
|
94
|
+
| Path | Case-**sensitive**. `/Auth/Callback` does **not** match `/auth/callback`. A trailing slash is insignificant in either direction. Dot segments resolve first, so `/auth/callback/../admin` is compared as `/auth/admin`. An encoded slash (`%2F`) is not a path separator. |
|
|
95
|
+
| Query and fragment | **Ignored on both sides**, so the usual `?code=...&state=...` callback matches. |
|
|
96
|
+
| Userinfo | Any URL carrying `user:password@` is rejected. |
|
|
97
|
+
|
|
98
|
+
If a redirect is refused, the `400` response names the callback URL the server actually compared (scheme, host and path — query and fragment are stripped) and says how many entries are configured. That is usually enough to tell a near miss — a trailing slash, a port, a case difference — from a typo or an unset variable, without needing server logs.
|
|
99
|
+
|
|
100
|
+
#### A malformed entry fails the whole list, loudly
|
|
101
|
+
|
|
102
|
+
If **any** entry cannot be used as a trusted callback URL, the entire list is rejected and **the server fails to start** with an error naming the offending entry by position and value. Entries 1 and 3 do not quietly survive a bad entry 2.
|
|
103
|
+
|
|
104
|
+
This is deliberate. The friendlier alternative — skip the bad entry, honour the rest — makes the allowlist enforce something other than what you wrote, with no signal that it did: the refusal a dropped entry produces looks exactly like an exact-match miss. A startup failure is noisy, but it happens immediately and before any sign-in is served, rather than surfacing weeks later as an unexplained OAuth failure.
|
|
105
|
+
|
|
106
|
+
Entries are rejected when they are unparseable, use a scheme other than `https:`/`http:`, are plaintext `http:` to a non-loopback host, or carry `user:password@` userinfo. To recover, either fix the entry the error names, or unset the variable entirely to fall back to the built-in allowlist.
|
|
107
|
+
|
|
108
|
+
> The variable is `NEOTOMA_OAUTH_TRUSTED_CALLBACK_URLS`. Early planning notes for this feature called it `NEOTOMA_TRUSTED_OAUTH_CALLBACKS`; that name was never implemented and setting it has no effect.
|
|
109
|
+
|
|
67
110
|
See [Deployment Modes](deployment.md) and [Agent Access Control](agent_access_control.md).
|
|
68
111
|
|
|
69
112
|
## Encryption
|