@bevel-software/platform-core-backend 0.13.5 → 0.14.0
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/THIRD-PARTY-NOTICES.md +639 -433
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +6 -3
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +2 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +9 -0
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +12 -5
- package/dist/core-config.js.map +1 -1
- package/dist/modules/access-model/kb-read-filter.d.ts +12 -0
- package/dist/modules/access-model/kb-read-filter.d.ts.map +1 -1
- package/dist/modules/access-model/kb-read-filter.js +15 -0
- package/dist/modules/access-model/kb-read-filter.js.map +1 -1
- package/dist/modules/connection-probe/connection-probe.contract.d.ts +43 -0
- package/dist/modules/connection-probe/connection-probe.contract.d.ts.map +1 -0
- package/dist/modules/connection-probe/connection-probe.contract.js +2 -0
- package/dist/modules/connection-probe/connection-probe.contract.js.map +1 -0
- package/dist/modules/connection-probe/connection-probe.service.d.ts +94 -0
- package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -0
- package/dist/modules/connection-probe/connection-probe.service.js +684 -0
- package/dist/modules/connection-probe/connection-probe.service.js.map +1 -0
- package/dist/modules/connection-probe/index.d.ts +3 -0
- package/dist/modules/connection-probe/index.d.ts.map +1 -0
- package/dist/modules/connection-probe/index.js +3 -0
- package/dist/modules/connection-probe/index.js.map +1 -0
- package/dist/modules/diff/diff.routes.d.ts.map +1 -1
- package/dist/modules/diff/diff.routes.js +3 -5
- package/dist/modules/diff/diff.routes.js.map +1 -1
- package/dist/modules/kb-fs/mutex.d.ts +37 -0
- package/dist/modules/kb-fs/mutex.d.ts.map +1 -1
- package/dist/modules/kb-fs/mutex.js +48 -5
- package/dist/modules/kb-fs/mutex.js.map +1 -1
- package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.routes.js +95 -13
- package/dist/modules/mcp/mcp.routes.js.map +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.js +1 -1
- package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +6 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +31 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.js +10 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/mcp-server-edit.service.js +10 -4
- package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +83 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +9 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +181 -13
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +18 -1
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +98 -6
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts +2 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +98 -9
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +81 -8
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +220 -43
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +2 -5
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +5 -1
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +21 -4
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/shared/token-crypto.d.ts +17 -2
- package/dist/shared/token-crypto.d.ts.map +1 -1
- package/dist/shared/token-crypto.js +25 -8
- package/dist/shared/token-crypto.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/core-config.admin.test.ts +21 -0
- package/src/core/create-core-server.ts +7 -2
- package/src/core/create-core-services.ts +11 -0
- package/src/core-config.ts +14 -7
- package/src/modules/access-model/kb-read-filter.ts +22 -0
- package/src/modules/connection-probe/__tests__/connection-probe.service.test.ts +685 -0
- package/src/modules/connection-probe/connection-probe.contract.ts +44 -0
- package/src/modules/connection-probe/connection-probe.service.ts +734 -0
- package/src/modules/connection-probe/index.ts +2 -0
- package/src/modules/diff/diff.routes.ts +9 -5
- package/src/modules/kb-fs/__tests__/mutex.test.ts +107 -0
- package/src/modules/kb-fs/mutex.ts +50 -5
- package/src/modules/mcp/__tests__/mcp-routes-harness.ts +89 -0
- package/src/modules/mcp/__tests__/mcp.routes.delete.test.ts +6 -34
- package/src/modules/mcp/__tests__/mcp.routes.local-token.test.ts +8 -40
- package/src/modules/mcp/__tests__/mcp.routes.session.test.ts +226 -0
- package/src/modules/mcp/mcp.routes.ts +482 -398
- package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +12 -0
- package/src/modules/secrets-vault/__tests__/oauth-return-to.route.test.ts +10 -3
- package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +26 -0
- package/src/modules/secrets-vault/db-secrets-vault.service.ts +1 -1
- package/src/modules/secrets-vault/secrets-vault.routes.ts +35 -1
- package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +11 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.health-check.test.ts +104 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +56 -0
- package/src/modules/tool-manuals/mcp-json-discovery.ts +13 -1
- package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -4
- package/src/modules/tool-manuals/tool-manuals.contract.ts +89 -0
- package/src/modules/tool-manuals/tool-manuals.service.ts +196 -14
- package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +139 -0
- package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +337 -0
- package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +7 -1
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +95 -8
- package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +86 -0
- package/src/modules/workflow/git/git.service.ts +115 -7
- package/src/modules/workflow/workflow.routes.ts +104 -4
- package/src/modules/workflow/workflow.service.ts +245 -55
- package/src/modules/workspace/workspace.routes.ts +8 -4
- package/src/modules/workspace/workspace.service.ts +21 -3
- package/src/shared/__tests__/token-crypto.test.ts +34 -0
- package/src/shared/token-crypto.ts +28 -10
|
@@ -122,8 +122,10 @@ export async function createCoreServer(
|
|
|
122
122
|
// `exposedHeaders` lets a BROWSER-based MCP client (e.g. MCP Inspector) read
|
|
123
123
|
// the Streamable-HTTP session header off the `initialize` response — custom
|
|
124
124
|
// response headers are hidden from browser JS unless exposed, so without this
|
|
125
|
-
// the client can't send `Mcp-Session-Id` back and every follow-up
|
|
126
|
-
//
|
|
125
|
+
// the client can't send `Mcp-Session-Id` back at all, and every follow-up
|
|
126
|
+
// 400s with "Bad Request: Mcp-Session-Id header is required" — the
|
|
127
|
+
// missing-header case, not the unknown-session one (that answers 404
|
|
128
|
+
// "Session not found"). `WWW-Authenticate` is
|
|
127
129
|
// exposed so a browser client can read the 401 challenge and start the OAuth
|
|
128
130
|
// discovery flow. (Native clients like Claude Code aren't subject to CORS.)
|
|
129
131
|
app.use(
|
|
@@ -301,6 +303,7 @@ export async function createCoreServer(
|
|
|
301
303
|
secretsVault: core.secretsVaultService,
|
|
302
304
|
toolManualService: core.toolManualService,
|
|
303
305
|
accessControl: core.accessControl,
|
|
306
|
+
connectionProbe: core.connectionProbeService,
|
|
304
307
|
stateSecret: core.config.jwtSecret,
|
|
305
308
|
publicBackendUrl: core.config.publicBackendUrl,
|
|
306
309
|
publicFrontendUrl: core.config.publicFrontendUrl,
|
|
@@ -399,6 +402,8 @@ export async function createCoreServer(
|
|
|
399
402
|
core.workspaceService,
|
|
400
403
|
core.authService,
|
|
401
404
|
core.eventBus,
|
|
405
|
+
core.accessControl,
|
|
406
|
+
core.kbDirName,
|
|
402
407
|
));
|
|
403
408
|
// SSE event-bus surface. The route owns its own auth gating via the
|
|
404
409
|
// injected middleware (which accepts both Bearer and the `bevel_token`
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
McpOAuthDiscoveryService,
|
|
47
47
|
registerBevelSecretsVariableLoader,
|
|
48
48
|
} from '../modules/secrets-vault/index.js';
|
|
49
|
+
import { ConnectionProbeService } from '../modules/connection-probe/index.js';
|
|
49
50
|
import { GitService } from '../modules/workflow/git/git.service.js';
|
|
50
51
|
import { PullRequestService } from '../modules/workflow/git/pull-request.service.js';
|
|
51
52
|
import { WorkspaceMutex } from '../modules/kb-fs/mutex.js';
|
|
@@ -169,6 +170,7 @@ export interface CoreServices {
|
|
|
169
170
|
*/
|
|
170
171
|
kbDirName: string;
|
|
171
172
|
secretsVaultService: DbSecretsVaultService;
|
|
173
|
+
connectionProbeService: ConnectionProbeService;
|
|
172
174
|
externalApiKeyService: ExternalApiKeyService;
|
|
173
175
|
internalTokenService: InternalTokenService;
|
|
174
176
|
mcpService: McpService;
|
|
@@ -562,6 +564,14 @@ export async function createCoreServices(
|
|
|
562
564
|
// UTCP client can resolve `${VAR}` from the caller's secrets at tool-call time.
|
|
563
565
|
registerBevelSecretsVariableLoader(secretsVaultService);
|
|
564
566
|
|
|
567
|
+
// The credential probe: whether a tool's stored credential actually WORKS, as
|
|
568
|
+
// distinct from whether one is stored. Built here — after the vault and the
|
|
569
|
+
// tool catalog — because a probe needs both: the catalog to know what to
|
|
570
|
+
// call, the vault to resolve the credential to call it with. Holds no state
|
|
571
|
+
// and takes no `db`: a verdict is returned to the caller that asked for it and
|
|
572
|
+
// never outlives their page (see `ProbeVerdict`).
|
|
573
|
+
const connectionProbeService = new ConnectionProbeService(toolManualService, secretsVaultService);
|
|
574
|
+
|
|
565
575
|
// Zero-config OAuth for bare `type: mcp` `.tool`s: when the remote server
|
|
566
576
|
// demands OAuth (MCP authorization spec), discover its authorization server,
|
|
567
577
|
// dynamically register a public PKCE client, and persist the provider as the
|
|
@@ -835,6 +845,7 @@ export async function createCoreServices(
|
|
|
835
845
|
createSyncedGroupsMaterializer,
|
|
836
846
|
updateCheckService,
|
|
837
847
|
secretsVaultService,
|
|
848
|
+
connectionProbeService,
|
|
838
849
|
externalApiKeyService,
|
|
839
850
|
internalTokenService,
|
|
840
851
|
mcpService,
|
package/src/core-config.ts
CHANGED
|
@@ -2,6 +2,7 @@ import dotenv from 'dotenv';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { defaultKbTemplateDir } from './assets.js';
|
|
5
|
+
import { assertKeyDecodesTo32Bytes } from './shared/token-crypto.js';
|
|
5
6
|
|
|
6
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
8
|
dotenv.config({ path: path.resolve(__dirname, '../../../.env') });
|
|
@@ -337,19 +338,25 @@ export class CoreConfig {
|
|
|
337
338
|
.split(/[\s,]+/)
|
|
338
339
|
.map((d) => d.trim().toLowerCase().replace(/^[@.]+/, ''))
|
|
339
340
|
.filter((d) => d.length > 0);
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
''
|
|
345
|
-
).trim();
|
|
346
|
-
|
|
341
|
+
// Which variable actually supplied the key decides whose name a bad key
|
|
342
|
+
// is reported under: a legacy deploy still on the fallback chain must be
|
|
343
|
+
// told to fix the variable it set, not one it never heard of.
|
|
344
|
+
const secretsKeySource = (
|
|
345
|
+
['SECRETS_ENC_KEY', 'CONNECTOR_CONFIG_ENC_KEY', 'SHAREPOINT_TOKEN_ENC_KEY'] as const
|
|
346
|
+
).find((name) => (process.env[name] ?? '').trim() !== '');
|
|
347
|
+
this.secretsEncKey = secretsKeySource ? process.env[secretsKeySource]!.trim() : '';
|
|
348
|
+
if (!secretsKeySource) {
|
|
347
349
|
throw new Error(
|
|
348
350
|
'SECRETS_ENC_KEY is required — it encrypts the secrets vault, the MCP OAuth ' +
|
|
349
351
|
'tokens and the git credential saved from the setup screen. Generate one ' +
|
|
350
352
|
`with: node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"`,
|
|
351
353
|
);
|
|
352
354
|
}
|
|
355
|
+
// Validate the LENGTH here too, while the winning variable's name is in
|
|
356
|
+
// hand. Every later `new TokenCrypto(config.secretsEncKey)` blames
|
|
357
|
+
// SECRETS_ENC_KEY by default, which is only certainly right because a bad
|
|
358
|
+
// key never gets past this line.
|
|
359
|
+
assertKeyDecodesTo32Bytes(this.secretsEncKey, secretsKeySource);
|
|
353
360
|
this.internalTokenSecret = (process.env.INTERNAL_TOKEN_SECRET || '').trim();
|
|
354
361
|
// Setting DOMAIN declares "the bundled Caddy `https` profile fronts this
|
|
355
362
|
// deployment" — one proxy hop, and the public origin IS that domain. The
|
|
@@ -42,6 +42,28 @@ export function toKbRelative(p: string, kbDirName: string): string | null {
|
|
|
42
42
|
return rel.length > 0 ? rel : null;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* THE single-path read verdict every route module shares: may `userEmail`
|
|
47
|
+
* read the workspace-relative `wsPath`? Non-KB paths (outside `kbDirName`)
|
|
48
|
+
* carry no `read:` rules and pass; KB paths go through the FULL `canRead`
|
|
49
|
+
* (folder `access.md` chain + per-node frontmatter). Content, diff and
|
|
50
|
+
* history routes all gate through this one function so the rule cannot
|
|
51
|
+
* drift between the surfaces — a file's history and its diffs are its
|
|
52
|
+
* content, and must deny exactly where the content route denies. Throws
|
|
53
|
+
* whatever `canRead` throws: the caller decides how a verdict failure is
|
|
54
|
+
* reported, and MUST fail closed.
|
|
55
|
+
*/
|
|
56
|
+
export async function canReadWorkspacePath(
|
|
57
|
+
canRead: (workspaceId: string, userEmail: string, kbRelPath: string) => Promise<boolean>,
|
|
58
|
+
workspaceId: string,
|
|
59
|
+
userEmail: string,
|
|
60
|
+
kbDirName: string,
|
|
61
|
+
wsPath: string,
|
|
62
|
+
): Promise<boolean> {
|
|
63
|
+
const rel = toKbRelative(wsPath, kbDirName);
|
|
64
|
+
return rel === null || (await canRead(workspaceId, userEmail, rel));
|
|
65
|
+
}
|
|
66
|
+
|
|
45
67
|
/**
|
|
46
68
|
* Resolve read verdicts for a set of workspace-relative paths in ONE batched
|
|
47
69
|
* access call. Non-KB paths (outside `kbDirName`) are always readable — they
|