@vurb/core 3.2.3 → 3.3.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.
- package/README.md +677 -677
- package/dist/cli/constants.js +59 -59
- package/dist/cli/templates/config.js +26 -26
- package/dist/cli/templates/constants.d.ts +1 -1
- package/dist/cli/templates/constants.d.ts.map +1 -1
- package/dist/cli/templates/constants.js +1 -1
- package/dist/cli/templates/constants.js.map +1 -1
- package/dist/cli/templates/core.d.ts.map +1 -1
- package/dist/cli/templates/core.js +96 -169
- package/dist/cli/templates/core.js.map +1 -1
- package/dist/cli/templates/middleware.js +25 -25
- package/dist/cli/templates/readme.js +142 -142
- package/dist/cli/templates/testing.js +84 -84
- package/dist/cli/templates/tools.js +46 -46
- package/dist/cli/templates/vectors/database.js +69 -69
- package/dist/cli/templates/vectors/oauth.js +63 -63
- package/dist/cli/templates/vectors/openapi.js +97 -97
- package/dist/core/middleware/AuditTrail.d.ts +128 -0
- package/dist/core/middleware/AuditTrail.d.ts.map +1 -0
- package/dist/core/middleware/AuditTrail.js +94 -0
- package/dist/core/middleware/AuditTrail.js.map +1 -0
- package/dist/core/middleware/InputFirewall.d.ts +95 -0
- package/dist/core/middleware/InputFirewall.d.ts.map +1 -0
- package/dist/core/middleware/InputFirewall.js +104 -0
- package/dist/core/middleware/InputFirewall.js.map +1 -0
- package/dist/core/middleware/RateLimiter.d.ts +151 -0
- package/dist/core/middleware/RateLimiter.d.ts.map +1 -0
- package/dist/core/middleware/RateLimiter.js +121 -0
- package/dist/core/middleware/RateLimiter.js.map +1 -0
- package/dist/core/middleware/index.d.ts +6 -0
- package/dist/core/middleware/index.d.ts.map +1 -1
- package/dist/core/middleware/index.js +4 -0
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/index.d.ts +28 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/introspection/SemanticProbe.js +49 -49
- package/dist/observability/TelemetryEvent.d.ts +61 -1
- package/dist/observability/TelemetryEvent.d.ts.map +1 -1
- package/dist/presenter/JudgeChain.d.ts +129 -0
- package/dist/presenter/JudgeChain.d.ts.map +1 -0
- package/dist/presenter/JudgeChain.js +215 -0
- package/dist/presenter/JudgeChain.js.map +1 -0
- package/dist/presenter/PostProcessor.d.ts.map +1 -1
- package/dist/presenter/PostProcessor.js +11 -66
- package/dist/presenter/PostProcessor.js.map +1 -1
- package/dist/presenter/Presenter.d.ts +175 -37
- package/dist/presenter/Presenter.d.ts.map +1 -1
- package/dist/presenter/Presenter.js +265 -154
- package/dist/presenter/Presenter.js.map +1 -1
- package/dist/presenter/PresenterPipeline.d.ts +147 -0
- package/dist/presenter/PresenterPipeline.d.ts.map +1 -0
- package/dist/presenter/PresenterPipeline.js +271 -0
- package/dist/presenter/PresenterPipeline.js.map +1 -0
- package/dist/presenter/PromptFirewall.d.ts +160 -0
- package/dist/presenter/PromptFirewall.d.ts.map +1 -0
- package/dist/presenter/PromptFirewall.js +228 -0
- package/dist/presenter/PromptFirewall.js.map +1 -0
- package/dist/presenter/ResponseBuilder.d.ts +13 -0
- package/dist/presenter/ResponseBuilder.d.ts.map +1 -1
- package/dist/presenter/ResponseBuilder.js +28 -1
- package/dist/presenter/ResponseBuilder.js.map +1 -1
- package/dist/presenter/TelemetryCollector.d.ts +48 -0
- package/dist/presenter/TelemetryCollector.d.ts.map +1 -0
- package/dist/presenter/TelemetryCollector.js +93 -0
- package/dist/presenter/TelemetryCollector.js.map +1 -0
- package/dist/presenter/definePresenter.d.ts +112 -0
- package/dist/presenter/definePresenter.d.ts.map +1 -1
- package/dist/presenter/definePresenter.js +110 -0
- package/dist/presenter/definePresenter.js.map +1 -1
- package/dist/presenter/index.d.ts +6 -2
- package/dist/presenter/index.d.ts.map +1 -1
- package/dist/presenter/index.js +5 -1
- package/dist/presenter/index.js.map +1 -1
- package/dist/presenter/ui.d.ts +31 -8
- package/dist/presenter/ui.d.ts.map +1 -1
- package/dist/presenter/ui.js +16 -16
- package/dist/presenter/ui.js.map +1 -1
- package/dist/prompt/FluentPromptBuilder.d.ts.map +1 -1
- package/dist/resource/ResourceBuilder.d.ts +129 -0
- package/dist/resource/ResourceBuilder.d.ts.map +1 -0
- package/dist/resource/ResourceBuilder.js +93 -0
- package/dist/resource/ResourceBuilder.js.map +1 -0
- package/dist/resource/ResourceRegistry.d.ts +147 -0
- package/dist/resource/ResourceRegistry.d.ts.map +1 -0
- package/dist/resource/ResourceRegistry.js +234 -0
- package/dist/resource/ResourceRegistry.js.map +1 -0
- package/dist/resource/SubscriptionManager.d.ts +67 -0
- package/dist/resource/SubscriptionManager.d.ts.map +1 -0
- package/dist/resource/SubscriptionManager.js +86 -0
- package/dist/resource/SubscriptionManager.js.map +1 -0
- package/dist/resource/index.d.ts +13 -0
- package/dist/resource/index.d.ts.map +1 -0
- package/dist/resource/index.js +13 -0
- package/dist/resource/index.js.map +1 -0
- package/dist/server/ServerAttachment.d.ts +26 -0
- package/dist/server/ServerAttachment.d.ts.map +1 -1
- package/dist/server/ServerAttachment.js +70 -2
- package/dist/server/ServerAttachment.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/startServer.d.ts +22 -1
- package/dist/server/startServer.d.ts.map +1 -1
- package/dist/server/startServer.js +98 -5
- package/dist/server/startServer.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,79 +4,79 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/** Generate `prisma/schema.prisma` */
|
|
6
6
|
export function prismaSchema() {
|
|
7
|
-
return `// Prisma Schema — Database-Driven MCP Server
|
|
8
|
-
//
|
|
9
|
-
// The @vurb/prisma-gen generator reads annotations
|
|
10
|
-
// and auto-generates Presenters + ToolBuilders with:
|
|
11
|
-
// - Field-level security (/// @vurb.hide)
|
|
12
|
-
// - Tenant isolation
|
|
13
|
-
// - OOM protection
|
|
14
|
-
|
|
15
|
-
generator client {
|
|
16
|
-
provider = "prisma-client-js"
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
generator vurb {
|
|
20
|
-
provider = "@vurb/prisma-gen"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
datasource db {
|
|
24
|
-
provider = "postgresql"
|
|
25
|
-
url = env("DATABASE_URL")
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
model User {
|
|
29
|
-
id String @id @default(cuid())
|
|
30
|
-
email String @unique
|
|
31
|
-
name String
|
|
32
|
-
|
|
33
|
-
/// @vurb.hide — Stripped by the Egress Firewall before reaching the LLM
|
|
34
|
-
password String
|
|
35
|
-
|
|
36
|
-
role String @default("USER")
|
|
37
|
-
createdAt DateTime @default(now())
|
|
38
|
-
updatedAt DateTime @updatedAt
|
|
39
|
-
|
|
40
|
-
posts Post[]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
model Post {
|
|
44
|
-
id String @id @default(cuid())
|
|
45
|
-
title String
|
|
46
|
-
content String?
|
|
47
|
-
published Boolean @default(false)
|
|
48
|
-
createdAt DateTime @default(now())
|
|
49
|
-
|
|
50
|
-
author User @relation(fields: [authorId], references: [id])
|
|
51
|
-
authorId String
|
|
52
|
-
}
|
|
7
|
+
return `// Prisma Schema — Database-Driven MCP Server
|
|
8
|
+
//
|
|
9
|
+
// The @vurb/prisma-gen generator reads annotations
|
|
10
|
+
// and auto-generates Presenters + ToolBuilders with:
|
|
11
|
+
// - Field-level security (/// @vurb.hide)
|
|
12
|
+
// - Tenant isolation
|
|
13
|
+
// - OOM protection
|
|
14
|
+
|
|
15
|
+
generator client {
|
|
16
|
+
provider = "prisma-client-js"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
generator vurb {
|
|
20
|
+
provider = "@vurb/prisma-gen"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
datasource db {
|
|
24
|
+
provider = "postgresql"
|
|
25
|
+
url = env("DATABASE_URL")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
model User {
|
|
29
|
+
id String @id @default(cuid())
|
|
30
|
+
email String @unique
|
|
31
|
+
name String
|
|
32
|
+
|
|
33
|
+
/// @vurb.hide — Stripped by the Egress Firewall before reaching the LLM
|
|
34
|
+
password String
|
|
35
|
+
|
|
36
|
+
role String @default("USER")
|
|
37
|
+
createdAt DateTime @default(now())
|
|
38
|
+
updatedAt DateTime @updatedAt
|
|
39
|
+
|
|
40
|
+
posts Post[]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
model Post {
|
|
44
|
+
id String @id @default(cuid())
|
|
45
|
+
title String
|
|
46
|
+
content String?
|
|
47
|
+
published Boolean @default(false)
|
|
48
|
+
createdAt DateTime @default(now())
|
|
49
|
+
|
|
50
|
+
author User @relation(fields: [authorId], references: [id])
|
|
51
|
+
authorId String
|
|
52
|
+
}
|
|
53
53
|
`;
|
|
54
54
|
}
|
|
55
55
|
/** Generate `src/tools/db/users.ts` */
|
|
56
56
|
export function dbUsersToolTs() {
|
|
57
|
-
return `/**
|
|
58
|
-
* Database Users Tool — Prisma-Driven CRUD (Fluent API)
|
|
59
|
-
*
|
|
60
|
-
* Demonstrates:
|
|
61
|
-
* - f.query() with .withOptionalNumber() typed parameter
|
|
62
|
-
* - .handle(input, ctx) — input.take is typed as number | undefined
|
|
63
|
-
* - Implicit success() wrapping
|
|
64
|
-
*/
|
|
65
|
-
import { f } from '../../vurb.js';
|
|
66
|
-
|
|
67
|
-
export default f.query('db.list_users')
|
|
68
|
-
.describe('List users from the database')
|
|
69
|
-
.withOptionalNumber('take', 'Max results (1-50)')
|
|
70
|
-
.handle(async (input, ctx) => {
|
|
71
|
-
// TODO: Replace with your Prisma client
|
|
72
|
-
// const users = await ctx.db.user.findMany({ take: input.take ?? 10 });
|
|
73
|
-
// return users;
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
hint: 'Connect your Prisma client in src/context.ts to enable database queries.',
|
|
77
|
-
example: 'const users = await ctx.db.user.findMany({ take: 10 })',
|
|
78
|
-
};
|
|
79
|
-
});
|
|
57
|
+
return `/**
|
|
58
|
+
* Database Users Tool — Prisma-Driven CRUD (Fluent API)
|
|
59
|
+
*
|
|
60
|
+
* Demonstrates:
|
|
61
|
+
* - f.query() with .withOptionalNumber() typed parameter
|
|
62
|
+
* - .handle(input, ctx) — input.take is typed as number | undefined
|
|
63
|
+
* - Implicit success() wrapping
|
|
64
|
+
*/
|
|
65
|
+
import { f } from '../../vurb.js';
|
|
66
|
+
|
|
67
|
+
export default f.query('db.list_users')
|
|
68
|
+
.describe('List users from the database')
|
|
69
|
+
.withOptionalNumber('take', 'Max results (1-50)')
|
|
70
|
+
.handle(async (input, ctx) => {
|
|
71
|
+
// TODO: Replace with your Prisma client
|
|
72
|
+
// const users = await ctx.db.user.findMany({ take: input.take ?? 10 });
|
|
73
|
+
// return users;
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
hint: 'Connect your Prisma client in src/context.ts to enable database queries.',
|
|
77
|
+
example: 'const users = await ctx.db.user.findMany({ take: 10 })',
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
80
|
`;
|
|
81
81
|
}
|
|
82
82
|
//# sourceMappingURL=database.js.map
|
|
@@ -4,73 +4,73 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/** Generate `src/auth.ts` — OAuth Device Flow setup */
|
|
6
6
|
export function oauthSetupTs(config) {
|
|
7
|
-
return `/**
|
|
8
|
-
* OAuth Setup — Device Flow Authentication (RFC 8628)
|
|
9
|
-
*
|
|
10
|
-
* Pre-configured \`createAuthTool()\` with login, complete, status, logout actions.
|
|
11
|
-
* The \`requireAuth()\` middleware protects any tool with one line.
|
|
12
|
-
*
|
|
13
|
-
* 1. Set CLIENT_ID and AUTH endpoints in .env
|
|
14
|
-
* 2. Register the auth tool in server.ts
|
|
15
|
-
* 3. Use \`requireAuth()\` on protected tools
|
|
16
|
-
*/
|
|
17
|
-
import { createAuthTool, TokenManager } from '@vurb/oauth';
|
|
18
|
-
import type { ToolRegistry } from '@vurb/core';
|
|
19
|
-
|
|
20
|
-
export function registerAuth<TContext>(registry: ToolRegistry<TContext>): void {
|
|
21
|
-
const clientId = process.env['OAUTH_CLIENT_ID'];
|
|
22
|
-
const authEndpoint = process.env['OAUTH_AUTH_ENDPOINT'];
|
|
23
|
-
const tokenEndpoint = process.env['OAUTH_TOKEN_ENDPOINT'];
|
|
24
|
-
|
|
25
|
-
if (!clientId || !authEndpoint || !tokenEndpoint) {
|
|
26
|
-
console.error('⚠️ OAUTH_CLIENT_ID, OAUTH_AUTH_ENDPOINT, OAUTH_TOKEN_ENDPOINT are required in .env');
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const auth = createAuthTool({
|
|
31
|
-
clientId,
|
|
32
|
-
authorizationEndpoint: authEndpoint,
|
|
33
|
-
tokenEndpoint,
|
|
34
|
-
tokenManager: {
|
|
35
|
-
configDir: '.${config.name}',
|
|
36
|
-
envVar: '${config.name.toUpperCase().replace(/-/g, '_')}_TOKEN',
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
registry.register(auth);
|
|
41
|
-
console.error('🔐 OAuth Device Flow registered (auth.login → auth.complete → auth.status)');
|
|
42
|
-
}
|
|
7
|
+
return `/**
|
|
8
|
+
* OAuth Setup — Device Flow Authentication (RFC 8628)
|
|
9
|
+
*
|
|
10
|
+
* Pre-configured \`createAuthTool()\` with login, complete, status, logout actions.
|
|
11
|
+
* The \`requireAuth()\` middleware protects any tool with one line.
|
|
12
|
+
*
|
|
13
|
+
* 1. Set CLIENT_ID and AUTH endpoints in .env
|
|
14
|
+
* 2. Register the auth tool in server.ts
|
|
15
|
+
* 3. Use \`requireAuth()\` on protected tools
|
|
16
|
+
*/
|
|
17
|
+
import { createAuthTool, TokenManager } from '@vurb/oauth';
|
|
18
|
+
import type { ToolRegistry } from '@vurb/core';
|
|
19
|
+
|
|
20
|
+
export function registerAuth<TContext>(registry: ToolRegistry<TContext>): void {
|
|
21
|
+
const clientId = process.env['OAUTH_CLIENT_ID'];
|
|
22
|
+
const authEndpoint = process.env['OAUTH_AUTH_ENDPOINT'];
|
|
23
|
+
const tokenEndpoint = process.env['OAUTH_TOKEN_ENDPOINT'];
|
|
24
|
+
|
|
25
|
+
if (!clientId || !authEndpoint || !tokenEndpoint) {
|
|
26
|
+
console.error('⚠️ OAUTH_CLIENT_ID, OAUTH_AUTH_ENDPOINT, OAUTH_TOKEN_ENDPOINT are required in .env');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const auth = createAuthTool({
|
|
31
|
+
clientId,
|
|
32
|
+
authorizationEndpoint: authEndpoint,
|
|
33
|
+
tokenEndpoint,
|
|
34
|
+
tokenManager: {
|
|
35
|
+
configDir: '.${config.name}',
|
|
36
|
+
envVar: '${config.name.toUpperCase().replace(/-/g, '_')}_TOKEN',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
registry.register(auth);
|
|
41
|
+
console.error('🔐 OAuth Device Flow registered (auth.login → auth.complete → auth.status)');
|
|
42
|
+
}
|
|
43
43
|
`;
|
|
44
44
|
}
|
|
45
45
|
/** Generate `src/middleware/auth.ts` — requireAuth middleware */
|
|
46
46
|
export function oauthMiddlewareTs() {
|
|
47
|
-
return `/**
|
|
48
|
-
* Auth Middleware — Protect tools with requireAuth()
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* \`\`\`ts
|
|
52
|
-
* import { withAuth } from '../middleware/auth.js';
|
|
53
|
-
*
|
|
54
|
-
* export default f.query('projects.list')
|
|
55
|
-
* .describe('List all projects')
|
|
56
|
-
* .use(withAuth)
|
|
57
|
-
* .handle(async (input, ctx) => { /* authenticated */ });
|
|
58
|
-
* \`\`\`
|
|
59
|
-
*/
|
|
60
|
-
import { requireAuth } from '@vurb/oauth';
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Pre-configured auth middleware.
|
|
64
|
-
* Rejects unauthenticated requests with \`AUTH_REQUIRED\` + self-healing hints.
|
|
65
|
-
*/
|
|
66
|
-
export const withAuth = requireAuth({
|
|
67
|
-
extractToken: (ctx: unknown) => {
|
|
68
|
-
const obj = ctx as Record<string, unknown>;
|
|
69
|
-
return typeof obj['token'] === 'string' ? obj['token'] : null;
|
|
70
|
-
},
|
|
71
|
-
recoveryHint: 'Call auth action=login to authenticate via browser',
|
|
72
|
-
recoveryAction: 'auth',
|
|
73
|
-
});
|
|
47
|
+
return `/**
|
|
48
|
+
* Auth Middleware — Protect tools with requireAuth()
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* \`\`\`ts
|
|
52
|
+
* import { withAuth } from '../middleware/auth.js';
|
|
53
|
+
*
|
|
54
|
+
* export default f.query('projects.list')
|
|
55
|
+
* .describe('List all projects')
|
|
56
|
+
* .use(withAuth)
|
|
57
|
+
* .handle(async (input, ctx) => { /* authenticated */ });
|
|
58
|
+
* \`\`\`
|
|
59
|
+
*/
|
|
60
|
+
import { requireAuth } from '@vurb/oauth';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Pre-configured auth middleware.
|
|
64
|
+
* Rejects unauthenticated requests with \`AUTH_REQUIRED\` + self-healing hints.
|
|
65
|
+
*/
|
|
66
|
+
export const withAuth = requireAuth({
|
|
67
|
+
extractToken: (ctx: unknown) => {
|
|
68
|
+
const obj = ctx as Record<string, unknown>;
|
|
69
|
+
return typeof obj['token'] === 'string' ? obj['token'] : null;
|
|
70
|
+
},
|
|
71
|
+
recoveryHint: 'Call auth action=login to authenticate via browser',
|
|
72
|
+
recoveryAction: 'auth',
|
|
73
|
+
});
|
|
74
74
|
`;
|
|
75
75
|
}
|
|
76
76
|
//# sourceMappingURL=oauth.js.map
|
|
@@ -1,106 +1,106 @@
|
|
|
1
1
|
/** Generate `openapi.yaml` — Sample OpenAPI spec */
|
|
2
2
|
export function openapiYaml(config) {
|
|
3
|
-
return `# OpenAPI 3.0 Specification — Sample
|
|
4
|
-
#
|
|
5
|
-
# Replace this with your actual API spec, then run:
|
|
6
|
-
# npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
|
|
7
|
-
#
|
|
8
|
-
# The generator creates Presenters, Tools, Registry, and server
|
|
9
|
-
# bootstrap — all configurable via YAML annotations.
|
|
10
|
-
|
|
11
|
-
openapi: '3.0.3'
|
|
12
|
-
info:
|
|
13
|
-
title: '${config.name} API'
|
|
14
|
-
version: '0.1.0'
|
|
15
|
-
description: Sample API for Vurb OpenAPI generation
|
|
16
|
-
|
|
17
|
-
servers:
|
|
18
|
-
- url: http://localhost:3000/api
|
|
19
|
-
|
|
20
|
-
paths:
|
|
21
|
-
/health:
|
|
22
|
-
get:
|
|
23
|
-
operationId: getHealth
|
|
24
|
-
summary: Health check endpoint
|
|
25
|
-
responses:
|
|
26
|
-
'200':
|
|
27
|
-
description: Server health status
|
|
28
|
-
content:
|
|
29
|
-
application/json:
|
|
30
|
-
schema:
|
|
31
|
-
type: object
|
|
32
|
-
properties:
|
|
33
|
-
status:
|
|
34
|
-
type: string
|
|
35
|
-
example: healthy
|
|
36
|
-
uptime:
|
|
37
|
-
type: number
|
|
38
|
-
example: 12345.67
|
|
39
|
-
|
|
40
|
-
/users:
|
|
41
|
-
get:
|
|
42
|
-
operationId: listUsers
|
|
43
|
-
summary: List all users
|
|
44
|
-
parameters:
|
|
45
|
-
- name: limit
|
|
46
|
-
in: query
|
|
47
|
-
schema:
|
|
48
|
-
type: integer
|
|
49
|
-
minimum: 1
|
|
50
|
-
maximum: 100
|
|
51
|
-
default: 10
|
|
52
|
-
responses:
|
|
53
|
-
'200':
|
|
54
|
-
description: List of users
|
|
55
|
-
content:
|
|
56
|
-
application/json:
|
|
57
|
-
schema:
|
|
58
|
-
type: array
|
|
59
|
-
items:
|
|
60
|
-
$ref: '#/components/schemas/User'
|
|
61
|
-
|
|
62
|
-
components:
|
|
63
|
-
schemas:
|
|
64
|
-
User:
|
|
65
|
-
type: object
|
|
66
|
-
properties:
|
|
67
|
-
id:
|
|
68
|
-
type: string
|
|
69
|
-
name:
|
|
70
|
-
type: string
|
|
71
|
-
email:
|
|
72
|
-
type: string
|
|
3
|
+
return `# OpenAPI 3.0 Specification — Sample
|
|
4
|
+
#
|
|
5
|
+
# Replace this with your actual API spec, then run:
|
|
6
|
+
# npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
|
|
7
|
+
#
|
|
8
|
+
# The generator creates Presenters, Tools, Registry, and server
|
|
9
|
+
# bootstrap — all configurable via YAML annotations.
|
|
10
|
+
|
|
11
|
+
openapi: '3.0.3'
|
|
12
|
+
info:
|
|
13
|
+
title: '${config.name} API'
|
|
14
|
+
version: '0.1.0'
|
|
15
|
+
description: Sample API for Vurb OpenAPI generation
|
|
16
|
+
|
|
17
|
+
servers:
|
|
18
|
+
- url: http://localhost:3000/api
|
|
19
|
+
|
|
20
|
+
paths:
|
|
21
|
+
/health:
|
|
22
|
+
get:
|
|
23
|
+
operationId: getHealth
|
|
24
|
+
summary: Health check endpoint
|
|
25
|
+
responses:
|
|
26
|
+
'200':
|
|
27
|
+
description: Server health status
|
|
28
|
+
content:
|
|
29
|
+
application/json:
|
|
30
|
+
schema:
|
|
31
|
+
type: object
|
|
32
|
+
properties:
|
|
33
|
+
status:
|
|
34
|
+
type: string
|
|
35
|
+
example: healthy
|
|
36
|
+
uptime:
|
|
37
|
+
type: number
|
|
38
|
+
example: 12345.67
|
|
39
|
+
|
|
40
|
+
/users:
|
|
41
|
+
get:
|
|
42
|
+
operationId: listUsers
|
|
43
|
+
summary: List all users
|
|
44
|
+
parameters:
|
|
45
|
+
- name: limit
|
|
46
|
+
in: query
|
|
47
|
+
schema:
|
|
48
|
+
type: integer
|
|
49
|
+
minimum: 1
|
|
50
|
+
maximum: 100
|
|
51
|
+
default: 10
|
|
52
|
+
responses:
|
|
53
|
+
'200':
|
|
54
|
+
description: List of users
|
|
55
|
+
content:
|
|
56
|
+
application/json:
|
|
57
|
+
schema:
|
|
58
|
+
type: array
|
|
59
|
+
items:
|
|
60
|
+
$ref: '#/components/schemas/User'
|
|
61
|
+
|
|
62
|
+
components:
|
|
63
|
+
schemas:
|
|
64
|
+
User:
|
|
65
|
+
type: object
|
|
66
|
+
properties:
|
|
67
|
+
id:
|
|
68
|
+
type: string
|
|
69
|
+
name:
|
|
70
|
+
type: string
|
|
71
|
+
email:
|
|
72
|
+
type: string
|
|
73
73
|
`;
|
|
74
74
|
}
|
|
75
75
|
/** Generate `SETUP.md` — OpenAPI generation instructions */
|
|
76
76
|
export function openapiSetupMd() {
|
|
77
|
-
return `# OpenAPI Generator Setup
|
|
78
|
-
|
|
79
|
-
This project is configured for the **Legacy API Proxy** ingestion vector.
|
|
80
|
-
|
|
81
|
-
## Steps
|
|
82
|
-
|
|
83
|
-
1. Replace \`openapi.yaml\` with your actual OpenAPI 3.x spec
|
|
84
|
-
|
|
85
|
-
2. Generate the MCP server from the spec:
|
|
86
|
-
\`\`\`bash
|
|
87
|
-
npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
|
|
88
|
-
\`\`\`
|
|
89
|
-
|
|
90
|
-
3. The generator creates:
|
|
91
|
-
- Presenters with Zod schemas (Egress Firewall)
|
|
92
|
-
- Tool builders with typed handlers
|
|
93
|
-
- Registry setup with all endpoints
|
|
94
|
-
|
|
95
|
-
4. Import and register in \`src/server.ts\`:
|
|
96
|
-
\`\`\`typescript
|
|
97
|
-
import { generatedTools } from './generated/registry.js';
|
|
98
|
-
registry.registerAll(...generatedTools);
|
|
99
|
-
\`\`\`
|
|
100
|
-
|
|
101
|
-
## Documentation
|
|
102
|
-
|
|
103
|
-
See: [OpenAPI Generator](https://vurb.vinkius.com/openapi-gen)
|
|
77
|
+
return `# OpenAPI Generator Setup
|
|
78
|
+
|
|
79
|
+
This project is configured for the **Legacy API Proxy** ingestion vector.
|
|
80
|
+
|
|
81
|
+
## Steps
|
|
82
|
+
|
|
83
|
+
1. Replace \`openapi.yaml\` with your actual OpenAPI 3.x spec
|
|
84
|
+
|
|
85
|
+
2. Generate the MCP server from the spec:
|
|
86
|
+
\`\`\`bash
|
|
87
|
+
npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
|
|
88
|
+
\`\`\`
|
|
89
|
+
|
|
90
|
+
3. The generator creates:
|
|
91
|
+
- Presenters with Zod schemas (Egress Firewall)
|
|
92
|
+
- Tool builders with typed handlers
|
|
93
|
+
- Registry setup with all endpoints
|
|
94
|
+
|
|
95
|
+
4. Import and register in \`src/server.ts\`:
|
|
96
|
+
\`\`\`typescript
|
|
97
|
+
import { generatedTools } from './generated/registry.js';
|
|
98
|
+
registry.registerAll(...generatedTools);
|
|
99
|
+
\`\`\`
|
|
100
|
+
|
|
101
|
+
## Documentation
|
|
102
|
+
|
|
103
|
+
See: [OpenAPI Generator](https://vurb.vinkius.com/openapi-gen)
|
|
104
104
|
`;
|
|
105
105
|
}
|
|
106
106
|
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuditTrail — SOC2/GDPR Compliance Middleware
|
|
3
|
+
*
|
|
4
|
+
* Structured audit logging of every tool invocation via {@link TelemetrySink}.
|
|
5
|
+
* Emits `security.audit` events with identity, action, args hash, result
|
|
6
|
+
* status, and duration — providing a complete audit trail for compliance.
|
|
7
|
+
*
|
|
8
|
+
* SOC2 Coverage:
|
|
9
|
+
* - CC6.1 — Logical Access (identity.userId, identity.role)
|
|
10
|
+
* - CC7.2 — Monitoring (every invocation logged)
|
|
11
|
+
* - CC7.3 — Change Detection (argsHash for mutation tracking)
|
|
12
|
+
*
|
|
13
|
+
* GDPR Coverage:
|
|
14
|
+
* - Art.30 — Records of Processing (tool, action, identity, timestamp)
|
|
15
|
+
* - Art.5(1)(c) — Data Minimization (hashArgs: true — no PII in log)
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { auditTrail } from '@vurb/core';
|
|
20
|
+
*
|
|
21
|
+
* const billing = createTool('billing')
|
|
22
|
+
* .use(auditTrail({
|
|
23
|
+
* sink: telemetrySink,
|
|
24
|
+
* extractIdentity: (ctx) => ({
|
|
25
|
+
* userId: ctx.userId,
|
|
26
|
+
* role: ctx.role,
|
|
27
|
+
* }),
|
|
28
|
+
* }));
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @module
|
|
32
|
+
*/
|
|
33
|
+
import type { MiddlewareFn } from '../types.js';
|
|
34
|
+
/** Identity information extracted from the request context */
|
|
35
|
+
export interface AuditIdentity {
|
|
36
|
+
readonly userId?: string;
|
|
37
|
+
readonly role?: string;
|
|
38
|
+
readonly ip?: string;
|
|
39
|
+
readonly [key: string]: string | undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Result status for audit logging.
|
|
43
|
+
*/
|
|
44
|
+
export type AuditStatus = 'success' | 'error' | 'firewall_blocked' | 'rate_limited';
|
|
45
|
+
/**
|
|
46
|
+
* A single audit event emitted by the middleware.
|
|
47
|
+
*/
|
|
48
|
+
export interface SecurityAuditEvent {
|
|
49
|
+
readonly type: 'security.audit';
|
|
50
|
+
/** Tool name (e.g., 'billing') */
|
|
51
|
+
readonly tool: string;
|
|
52
|
+
/** Action name (e.g., 'create_invoice') */
|
|
53
|
+
readonly action: string;
|
|
54
|
+
/** Extracted identity information */
|
|
55
|
+
readonly identity: AuditIdentity;
|
|
56
|
+
/** SHA-256 hash of the arguments (or 'none' if disabled) */
|
|
57
|
+
readonly argsHash: string;
|
|
58
|
+
/** Execution result status */
|
|
59
|
+
readonly status: AuditStatus;
|
|
60
|
+
/** Execution duration in milliseconds */
|
|
61
|
+
readonly durationMs: number;
|
|
62
|
+
/** Epoch milliseconds */
|
|
63
|
+
readonly timestamp: number;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Sink function for audit events.
|
|
67
|
+
* Fire-and-forget — dropping events must never affect the server.
|
|
68
|
+
*/
|
|
69
|
+
export type AuditSink = (event: SecurityAuditEvent) => void;
|
|
70
|
+
/**
|
|
71
|
+
* Configuration for the AuditTrail middleware.
|
|
72
|
+
*/
|
|
73
|
+
export interface AuditTrailConfig {
|
|
74
|
+
/**
|
|
75
|
+
* Sink function for audit events.
|
|
76
|
+
* Can be a TelemetrySink, a logging function, or any other consumer.
|
|
77
|
+
*/
|
|
78
|
+
readonly sink: AuditSink;
|
|
79
|
+
/**
|
|
80
|
+
* Tool name to include in audit events.
|
|
81
|
+
* Should match the tool's registered name (e.g., 'billing').
|
|
82
|
+
*/
|
|
83
|
+
readonly toolName?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Field name used as the action discriminator in tool arguments.
|
|
86
|
+
* Defaults to `'action'`. Set to the correct discriminator for
|
|
87
|
+
* non-standard tools (e.g., `'command'`, `'operation'`).
|
|
88
|
+
*
|
|
89
|
+
* @default 'action'
|
|
90
|
+
*/
|
|
91
|
+
readonly actionField?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Extract identity information from the request context.
|
|
94
|
+
* Return fields relevant for your compliance requirements.
|
|
95
|
+
*
|
|
96
|
+
* @param ctx - Request context
|
|
97
|
+
* @returns Identity object for audit logging
|
|
98
|
+
*/
|
|
99
|
+
readonly extractIdentity?: (ctx: unknown) => AuditIdentity;
|
|
100
|
+
/**
|
|
101
|
+
* Whether to hash the arguments (SHA-256).
|
|
102
|
+
* When `true`, args are hashed for change detection without storing PII.
|
|
103
|
+
*
|
|
104
|
+
* @default true
|
|
105
|
+
*/
|
|
106
|
+
readonly hashArgs?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* What level of result detail to log.
|
|
109
|
+
*
|
|
110
|
+
* - `'status'` — Log only success/error status (recommended)
|
|
111
|
+
* - `'none'` — Don't log result at all
|
|
112
|
+
*
|
|
113
|
+
* @default 'status'
|
|
114
|
+
*/
|
|
115
|
+
readonly logResult?: 'status' | 'none';
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create an AuditTrail middleware for SOC2/GDPR compliance.
|
|
119
|
+
*
|
|
120
|
+
* Logs every tool invocation with identity, args hash, status,
|
|
121
|
+
* and duration. The audit event is emitted AFTER the handler
|
|
122
|
+
* completes (or fails), capturing the full lifecycle.
|
|
123
|
+
*
|
|
124
|
+
* @param config - Audit trail configuration
|
|
125
|
+
* @returns A middleware function compatible with `.use()`
|
|
126
|
+
*/
|
|
127
|
+
export declare function auditTrail(config: AuditTrailConfig): MiddlewareFn<unknown>;
|
|
128
|
+
//# sourceMappingURL=AuditTrail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditTrail.d.ts","sourceRoot":"","sources":["../../../src/core/middleware/AuditTrail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,kBAAkB,GAAG,cAAc,CAAC;AAEpF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,aAAa,CAAC;IAE3D;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC1C;AAyBD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,YAAY,CAAC,OAAO,CAAC,CA+C1E"}
|