@bevel-software/platform-core-backend 0.13.6 → 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/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +2 -1
- 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/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 +3 -0
- 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/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
|
@@ -303,6 +303,7 @@ export async function createCoreServer(
|
|
|
303
303
|
secretsVault: core.secretsVaultService,
|
|
304
304
|
toolManualService: core.toolManualService,
|
|
305
305
|
accessControl: core.accessControl,
|
|
306
|
+
connectionProbe: core.connectionProbeService,
|
|
306
307
|
stateSecret: core.config.jwtSecret,
|
|
307
308
|
publicBackendUrl: core.config.publicBackendUrl,
|
|
308
309
|
publicFrontendUrl: core.config.publicFrontendUrl,
|
|
@@ -401,6 +402,8 @@ export async function createCoreServer(
|
|
|
401
402
|
core.workspaceService,
|
|
402
403
|
core.authService,
|
|
403
404
|
core.eventBus,
|
|
405
|
+
core.accessControl,
|
|
406
|
+
core.kbDirName,
|
|
404
407
|
));
|
|
405
408
|
// SSE event-bus surface. The route owns its own auth gating via the
|
|
406
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
|