@vurb/core 3.2.0 → 3.2.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/README.md +677 -677
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/deploy.js +28 -2
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/constants.d.ts.map +1 -1
- package/dist/cli/constants.js +59 -58
- package/dist/cli/constants.js.map +1 -1
- package/dist/cli/templates/config.js +26 -26
- package/dist/cli/templates/core.js +168 -168
- package/dist/cli/templates/middleware.js +25 -25
- package/dist/cli/templates/presenter.js +1 -1
- package/dist/cli/templates/presenter.js.map +1 -1
- package/dist/cli/templates/prompt.js +1 -1
- package/dist/cli/templates/prompt.js.map +1 -1
- 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/cli/templates/vectors/workflow.js +1 -1
- package/dist/cli/templates/vectors/workflow.js.map +1 -1
- package/dist/cli/utils.js +1 -1
- package/dist/cli/utils.js.map +1 -1
- package/dist/client/createTypedRegistry.js +1 -1
- package/dist/converters/ConverterBase.d.ts +1 -1
- package/dist/converters/ConverterBase.js +1 -1
- package/dist/core/StandardSchema.d.ts +1 -1
- package/dist/core/StandardSchema.js +1 -1
- package/dist/core/builder/GroupedToolBuilder.d.ts +2 -2
- package/dist/core/builder/GroupedToolBuilder.js +2 -2
- package/dist/core/builder/defineTool.d.ts +1 -1
- package/dist/core/builder/defineTool.js +1 -1
- package/dist/core/createGroup.d.ts +1 -1
- package/dist/core/createGroup.js +1 -1
- package/dist/core/initVurb.d.ts +1 -1
- package/dist/core/initVurb.js +1 -1
- package/dist/core/registry/ToolFilterEngine.d.ts +1 -1
- package/dist/core/registry/ToolFilterEngine.d.ts.map +1 -1
- package/dist/core/registry/ToolFilterEngine.js +1 -1
- package/dist/core/registry/ToolFilterEngine.js.map +1 -1
- package/dist/core/registry/ToolRegistry.d.ts +2 -2
- package/dist/core/registry/ToolRegistry.d.ts.map +1 -1
- package/dist/core/registry/ToolRegistry.js +2 -2
- package/dist/core/registry/ToolRegistry.js.map +1 -1
- package/dist/core/response.d.ts +1 -1
- package/dist/core/response.js +1 -1
- package/dist/core/result.d.ts +1 -1
- package/dist/core/result.js +1 -1
- package/dist/domain/Annotations.d.ts +1 -1
- package/dist/domain/Icon.d.ts +1 -1
- package/dist/domain/Prompt.d.ts +1 -1
- package/dist/domain/Prompt.js +1 -1
- package/dist/domain/PromptArgument.d.ts +1 -1
- package/dist/domain/PromptArgument.js +1 -1
- package/dist/domain/Resource.d.ts +1 -1
- package/dist/domain/Resource.js +1 -1
- package/dist/domain/Role.d.ts +1 -1
- package/dist/domain/Role.js +1 -1
- package/dist/domain/Tool.d.ts +1 -1
- package/dist/domain/Tool.js +1 -1
- package/dist/domain/ToolAnnotations.d.ts +1 -1
- package/dist/fsm/StateMachineGate.d.ts +1 -1
- package/dist/fsm/StateMachineGate.js +1 -1
- package/dist/introspection/GovernanceObserver.d.ts +1 -1
- package/dist/introspection/GovernanceObserver.js +1 -1
- package/dist/introspection/SemanticProbe.js +49 -49
- package/dist/observability/DebugObserver.d.ts +1 -1
- package/dist/observability/DebugObserver.js +1 -1
- package/dist/presenter/Presenter.d.ts +4 -4
- package/dist/presenter/Presenter.js +3 -3
- package/dist/presenter/ResponseBuilder.d.ts +2 -2
- package/dist/presenter/ResponseBuilder.js +2 -2
- package/dist/presenter/definePresenter.d.ts +1 -1
- package/dist/presenter/definePresenter.js +1 -1
- package/dist/presenter/suggest.d.ts +1 -1
- package/dist/presenter/suggest.js +1 -1
- package/dist/presenter/typeHelpers.d.ts +1 -1
- package/dist/presenter/typeHelpers.js +1 -1
- package/dist/presenter/ui.d.ts +2 -2
- package/dist/presenter/ui.js +2 -2
- package/dist/prompt/FluentPromptBuilder.d.ts.map +1 -1
- package/dist/prompt/PromptMessage.d.ts +2 -2
- package/dist/prompt/PromptMessage.js +2 -2
- package/dist/prompt/PromptRegistry.d.ts +1 -1
- package/dist/prompt/PromptRegistry.js +1 -1
- package/dist/server/DevServer.d.ts +1 -1
- package/dist/server/DevServer.js +1 -1
- package/dist/server/autoDiscover.js +1 -1
- package/dist/server/startServer.d.ts +1 -1
- package/dist/server/startServer.d.ts.map +1 -1
- package/dist/server/startServer.js +53 -2
- package/dist/server/startServer.js.map +1 -1
- package/dist/testing/MvaMetaSymbol.d.ts +1 -1
- package/dist/testing/MvaMetaSymbol.js +1 -1
- package/package.json +1 -1
|
@@ -11,160 +11,160 @@ export function readme(config) {
|
|
|
11
11
|
const sseNote = config.transport === 'sse'
|
|
12
12
|
? `\n> **Note:** Streamable HTTP transport requires the server to be running first. Run \\\`npm start\\\` before connecting.`
|
|
13
13
|
: '';
|
|
14
|
-
return `# ${config.name}
|
|
15
|
-
|
|
16
|
-
MCP Server built with [Vurb](https://vurb.vinkius.com/) — the MVA framework for the Model Context Protocol.
|
|
17
|
-
|
|
18
|
-
## Quick Start
|
|
19
|
-
|
|
20
|
-
\`\`\`bash
|
|
21
|
-
npm install
|
|
22
|
-
vurb dev
|
|
23
|
-
\`\`\`
|
|
24
|
-
${config.testing ? `
|
|
25
|
-
## Testing
|
|
26
|
-
|
|
27
|
-
\`\`\`bash
|
|
28
|
-
npm test
|
|
29
|
-
\`\`\`
|
|
30
|
-
` : ''}
|
|
31
|
-
## Project Structure
|
|
32
|
-
|
|
33
|
-
\`\`\`
|
|
34
|
-
src/
|
|
35
|
-
├── vurb.ts # initVurb<AppContext>() — context center
|
|
36
|
-
├── context.ts # AppContext type + factory
|
|
37
|
-
├── server.ts # Bootstrap with autoDiscover
|
|
38
|
-
├── tools/ # Drop a file → it's a tool (autoDiscover)
|
|
39
|
-
│ └── system/
|
|
40
|
-
│ ├── health.ts # Health check with Presenter
|
|
41
|
-
│ └── echo.ts # Echo for connectivity testing
|
|
42
|
-
├── presenters/ # MVA View Layer (Egress Firewall)
|
|
43
|
-
│ └── SystemPresenter.ts
|
|
44
|
-
├── prompts/ # MCP Prompt Engine
|
|
45
|
-
│ └── greet.ts
|
|
46
|
-
└── middleware/ # RBAC guards
|
|
47
|
-
└── auth.ts
|
|
48
|
-
\`\`\`
|
|
49
|
-
|
|
50
|
-
## Client Configuration
|
|
51
|
-
|
|
52
|
-
### Cursor Editor
|
|
53
|
-
|
|
54
|
-
> **Already configured!** The \`.cursor/mcp.json\` file was generated automatically.
|
|
55
|
-
> Just open this folder in Cursor and the server connects instantly.
|
|
56
|
-
${sseNote}
|
|
57
|
-
|
|
58
|
-
### Claude Desktop
|
|
59
|
-
|
|
60
|
-
Add to your \`claude_desktop_config.json\`:
|
|
61
|
-
|
|
62
|
-
\`\`\`json
|
|
63
|
-
${clientConfig}
|
|
64
|
-
\`\`\`
|
|
65
|
-
${vectorReadmeSection(config)}
|
|
66
|
-
## Adding New Tools
|
|
67
|
-
|
|
68
|
-
Create a new file in \`src/tools/\`. It's automatically discovered:
|
|
69
|
-
|
|
70
|
-
\`\`\`typescript
|
|
71
|
-
// src/tools/my-domain/my-tool.ts
|
|
72
|
-
import { f } from '../../vurb.js';
|
|
73
|
-
|
|
74
|
-
export default f.query('my_domain.my_tool')
|
|
75
|
-
.describe('What this tool does')
|
|
76
|
-
.withString('query', 'Search query')
|
|
77
|
-
.handle(async (input, ctx) => {
|
|
78
|
-
return { result: input.query };
|
|
79
|
-
});
|
|
80
|
-
\`\`\`
|
|
81
|
-
|
|
82
|
-
No registration needed. The \`autoDiscover()\` system picks it up automatically.
|
|
83
|
-
|
|
84
|
-
## Documentation
|
|
85
|
-
|
|
86
|
-
- [Vurb Docs](https://vurb.vinkius.com/)
|
|
87
|
-
- [Presenter — Egress Firewall](https://vurb.vinkius.com/presenter)
|
|
88
|
-
- [DX Guide — initVurb()](https://vurb.vinkius.com/dx-guide)
|
|
89
|
-
- [Testing](https://vurb.vinkius.com/testing)
|
|
14
|
+
return `# ${config.name}
|
|
15
|
+
|
|
16
|
+
MCP Server built with [Vurb](https://vurb.vinkius.com/) — the MVA framework for the Model Context Protocol.
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
\`\`\`bash
|
|
21
|
+
npm install
|
|
22
|
+
vurb dev
|
|
23
|
+
\`\`\`
|
|
24
|
+
${config.testing ? `
|
|
25
|
+
## Testing
|
|
26
|
+
|
|
27
|
+
\`\`\`bash
|
|
28
|
+
npm test
|
|
29
|
+
\`\`\`
|
|
30
|
+
` : ''}
|
|
31
|
+
## Project Structure
|
|
32
|
+
|
|
33
|
+
\`\`\`
|
|
34
|
+
src/
|
|
35
|
+
├── vurb.ts # initVurb<AppContext>() — context center
|
|
36
|
+
├── context.ts # AppContext type + factory
|
|
37
|
+
├── server.ts # Bootstrap with autoDiscover
|
|
38
|
+
├── tools/ # Drop a file → it's a tool (autoDiscover)
|
|
39
|
+
│ └── system/
|
|
40
|
+
│ ├── health.ts # Health check with Presenter
|
|
41
|
+
│ └── echo.ts # Echo for connectivity testing
|
|
42
|
+
├── presenters/ # MVA View Layer (Egress Firewall)
|
|
43
|
+
│ └── SystemPresenter.ts
|
|
44
|
+
├── prompts/ # MCP Prompt Engine
|
|
45
|
+
│ └── greet.ts
|
|
46
|
+
└── middleware/ # RBAC guards
|
|
47
|
+
└── auth.ts
|
|
48
|
+
\`\`\`
|
|
49
|
+
|
|
50
|
+
## Client Configuration
|
|
51
|
+
|
|
52
|
+
### Cursor Editor
|
|
53
|
+
|
|
54
|
+
> **Already configured!** The \`.cursor/mcp.json\` file was generated automatically.
|
|
55
|
+
> Just open this folder in Cursor and the server connects instantly.
|
|
56
|
+
${sseNote}
|
|
57
|
+
|
|
58
|
+
### Claude Desktop
|
|
59
|
+
|
|
60
|
+
Add to your \`claude_desktop_config.json\`:
|
|
61
|
+
|
|
62
|
+
\`\`\`json
|
|
63
|
+
${clientConfig}
|
|
64
|
+
\`\`\`
|
|
65
|
+
${vectorReadmeSection(config)}
|
|
66
|
+
## Adding New Tools
|
|
67
|
+
|
|
68
|
+
Create a new file in \`src/tools/\`. It's automatically discovered:
|
|
69
|
+
|
|
70
|
+
\`\`\`typescript
|
|
71
|
+
// src/tools/my-domain/my-tool.ts
|
|
72
|
+
import { f } from '../../vurb.js';
|
|
73
|
+
|
|
74
|
+
export default f.query('my_domain.my_tool')
|
|
75
|
+
.describe('What this tool does')
|
|
76
|
+
.withString('query', 'Search query')
|
|
77
|
+
.handle(async (input, ctx) => {
|
|
78
|
+
return { result: input.query };
|
|
79
|
+
});
|
|
80
|
+
\`\`\`
|
|
81
|
+
|
|
82
|
+
No registration needed. The \`autoDiscover()\` system picks it up automatically.
|
|
83
|
+
|
|
84
|
+
## Documentation
|
|
85
|
+
|
|
86
|
+
- [Vurb Docs](https://vurb.vinkius.com/)
|
|
87
|
+
- [Presenter — Egress Firewall](https://vurb.vinkius.com/presenter)
|
|
88
|
+
- [DX Guide — initVurb()](https://vurb.vinkius.com/dx-guide)
|
|
89
|
+
- [Testing](https://vurb.vinkius.com/testing)
|
|
90
90
|
`;
|
|
91
91
|
}
|
|
92
92
|
/** Vector-specific README section */
|
|
93
93
|
function vectorReadmeSection(config) {
|
|
94
94
|
switch (config.vector) {
|
|
95
95
|
case 'prisma':
|
|
96
|
-
return `
|
|
97
|
-
## Database Setup (Prisma)
|
|
98
|
-
|
|
99
|
-
1. Configure your database URL in \`.env\`:
|
|
100
|
-
\`\`\`
|
|
101
|
-
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
|
|
102
|
-
\`\`\`
|
|
103
|
-
|
|
104
|
-
2. Edit \`prisma/schema.prisma\` to define your models
|
|
105
|
-
|
|
106
|
-
3. Generate the Prisma client and Vurb tools:
|
|
107
|
-
\`\`\`bash
|
|
108
|
-
npm run db:generate
|
|
109
|
-
\`\`\`
|
|
110
|
-
|
|
111
|
-
4. Push the schema to your database:
|
|
112
|
-
\`\`\`bash
|
|
113
|
-
npm run db:push
|
|
114
|
-
\`\`\`
|
|
115
|
-
|
|
116
|
-
Use \`/// @vurb.hide\` on sensitive fields to strip them from the Egress Firewall.
|
|
96
|
+
return `
|
|
97
|
+
## Database Setup (Prisma)
|
|
98
|
+
|
|
99
|
+
1. Configure your database URL in \`.env\`:
|
|
100
|
+
\`\`\`
|
|
101
|
+
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
|
|
102
|
+
\`\`\`
|
|
103
|
+
|
|
104
|
+
2. Edit \`prisma/schema.prisma\` to define your models
|
|
105
|
+
|
|
106
|
+
3. Generate the Prisma client and Vurb tools:
|
|
107
|
+
\`\`\`bash
|
|
108
|
+
npm run db:generate
|
|
109
|
+
\`\`\`
|
|
110
|
+
|
|
111
|
+
4. Push the schema to your database:
|
|
112
|
+
\`\`\`bash
|
|
113
|
+
npm run db:push
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
Use \`/// @vurb.hide\` on sensitive fields to strip them from the Egress Firewall.
|
|
117
117
|
`;
|
|
118
118
|
case 'n8n':
|
|
119
|
-
return `
|
|
120
|
-
## n8n Workflow Setup
|
|
121
|
-
|
|
122
|
-
1. Configure your n8n instance in \`.env\`:
|
|
123
|
-
\`\`\`
|
|
124
|
-
N8N_BASE_URL=http://localhost:5678
|
|
125
|
-
N8N_API_KEY=your-api-key
|
|
126
|
-
\`\`\`
|
|
127
|
-
|
|
128
|
-
2. The connector in \`src/n8n.ts\` auto-discovers webhook workflows
|
|
129
|
-
and registers them as MCP tools.
|
|
119
|
+
return `
|
|
120
|
+
## n8n Workflow Setup
|
|
121
|
+
|
|
122
|
+
1. Configure your n8n instance in \`.env\`:
|
|
123
|
+
\`\`\`
|
|
124
|
+
N8N_BASE_URL=http://localhost:5678
|
|
125
|
+
N8N_API_KEY=your-api-key
|
|
126
|
+
\`\`\`
|
|
127
|
+
|
|
128
|
+
2. The connector in \`src/n8n.ts\` auto-discovers webhook workflows
|
|
129
|
+
and registers them as MCP tools.
|
|
130
130
|
`;
|
|
131
131
|
case 'openapi':
|
|
132
|
-
return `
|
|
133
|
-
## OpenAPI Generator Setup
|
|
134
|
-
|
|
135
|
-
1. Replace \`openapi.yaml\` with your actual OpenAPI 3.x spec
|
|
136
|
-
|
|
137
|
-
2. Generate the MCP server from the spec:
|
|
138
|
-
\`\`\`bash
|
|
139
|
-
npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
|
|
140
|
-
\`\`\`
|
|
141
|
-
|
|
142
|
-
3. Import and register the generated tools in \`src/server.ts\`
|
|
132
|
+
return `
|
|
133
|
+
## OpenAPI Generator Setup
|
|
134
|
+
|
|
135
|
+
1. Replace \`openapi.yaml\` with your actual OpenAPI 3.x spec
|
|
136
|
+
|
|
137
|
+
2. Generate the MCP server from the spec:
|
|
138
|
+
\`\`\`bash
|
|
139
|
+
npx @vurb/openapi-gen ./openapi.yaml --outDir ./src/generated
|
|
140
|
+
\`\`\`
|
|
141
|
+
|
|
142
|
+
3. Import and register the generated tools in \`src/server.ts\`
|
|
143
143
|
`;
|
|
144
144
|
case 'oauth':
|
|
145
|
-
return `
|
|
146
|
-
## OAuth Device Flow Setup
|
|
147
|
-
|
|
148
|
-
1. Configure your OAuth provider in \`.env\`:
|
|
149
|
-
\`\`\`
|
|
150
|
-
OAUTH_CLIENT_ID=your-client-id
|
|
151
|
-
OAUTH_AUTH_ENDPOINT=https://api.example.com/oauth/device/code
|
|
152
|
-
OAUTH_TOKEN_ENDPOINT=https://api.example.com/oauth/device/token
|
|
153
|
-
\`\`\`
|
|
154
|
-
|
|
155
|
-
2. The auth tool in \`src/auth.ts\` is pre-configured with login, complete, status, and logout actions.
|
|
156
|
-
|
|
157
|
-
3. Protect any tool with the \`withAuth\` middleware from \`src/middleware/auth.ts\`:
|
|
158
|
-
\`\`\`ts
|
|
159
|
-
import { withAuth } from '../middleware/auth.js';
|
|
160
|
-
|
|
161
|
-
export default f.query('protected.action')
|
|
162
|
-
.describe('A protected query')
|
|
163
|
-
.use(withAuth)
|
|
164
|
-
.handle(async (input, ctx) => {
|
|
165
|
-
// ctx is authenticated
|
|
166
|
-
});
|
|
167
|
-
\`\`\`
|
|
145
|
+
return `
|
|
146
|
+
## OAuth Device Flow Setup
|
|
147
|
+
|
|
148
|
+
1. Configure your OAuth provider in \`.env\`:
|
|
149
|
+
\`\`\`
|
|
150
|
+
OAUTH_CLIENT_ID=your-client-id
|
|
151
|
+
OAUTH_AUTH_ENDPOINT=https://api.example.com/oauth/device/code
|
|
152
|
+
OAUTH_TOKEN_ENDPOINT=https://api.example.com/oauth/device/token
|
|
153
|
+
\`\`\`
|
|
154
|
+
|
|
155
|
+
2. The auth tool in \`src/auth.ts\` is pre-configured with login, complete, status, and logout actions.
|
|
156
|
+
|
|
157
|
+
3. Protect any tool with the \`withAuth\` middleware from \`src/middleware/auth.ts\`:
|
|
158
|
+
\`\`\`ts
|
|
159
|
+
import { withAuth } from '../middleware/auth.js';
|
|
160
|
+
|
|
161
|
+
export default f.query('protected.action')
|
|
162
|
+
.describe('A protected query')
|
|
163
|
+
.use(withAuth)
|
|
164
|
+
.handle(async (input, ctx) => {
|
|
165
|
+
// ctx is authenticated
|
|
166
|
+
});
|
|
167
|
+
\`\`\`
|
|
168
168
|
`;
|
|
169
169
|
default:
|
|
170
170
|
return '';
|
|
@@ -4,98 +4,98 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/** Generate `vitest.config.ts` */
|
|
6
6
|
export function vitestConfig() {
|
|
7
|
-
return `import { defineConfig } from 'vitest/config';
|
|
8
|
-
|
|
9
|
-
export default defineConfig({
|
|
10
|
-
test: {
|
|
11
|
-
include: ['tests/**/*.test.ts'],
|
|
12
|
-
},
|
|
13
|
-
});
|
|
7
|
+
return `import { defineConfig } from 'vitest/config';
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
test: {
|
|
11
|
+
include: ['tests/**/*.test.ts'],
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
14
|
`;
|
|
15
15
|
}
|
|
16
16
|
/** Generate `tests/setup.ts` — Test infrastructure */
|
|
17
17
|
export function testSetupTs() {
|
|
18
|
-
return `/**
|
|
19
|
-
* Test Setup — In-Memory MVA Emulator
|
|
20
|
-
*
|
|
21
|
-
* Creates a VurbTester that runs the full pipeline
|
|
22
|
-
* (Zod → Middleware → Handler → Egress Firewall)
|
|
23
|
-
* without any network transport.
|
|
24
|
-
*
|
|
25
|
-
* 2ms per test. $0.00 in tokens. Zero servers.
|
|
26
|
-
*/
|
|
27
|
-
import { fileURLToPath } from 'node:url';
|
|
28
|
-
import { createVurbTester } from '@vurb/testing';
|
|
29
|
-
import { autoDiscover } from 'vurb';
|
|
30
|
-
import { f } from '../src/vurb.js';
|
|
31
|
-
|
|
32
|
-
const registry = f.registry();
|
|
33
|
-
await autoDiscover(registry, fileURLToPath(new URL('../src/tools', import.meta.url)));
|
|
34
|
-
|
|
35
|
-
export const tester = createVurbTester(registry, {
|
|
36
|
-
contextFactory: () => ({
|
|
37
|
-
role: 'ADMIN' as const,
|
|
38
|
-
tenantId: 'test-tenant',
|
|
39
|
-
}),
|
|
40
|
-
});
|
|
18
|
+
return `/**
|
|
19
|
+
* Test Setup — In-Memory MVA Emulator
|
|
20
|
+
*
|
|
21
|
+
* Creates a VurbTester that runs the full pipeline
|
|
22
|
+
* (Zod → Middleware → Handler → Egress Firewall)
|
|
23
|
+
* without any network transport.
|
|
24
|
+
*
|
|
25
|
+
* 2ms per test. $0.00 in tokens. Zero servers.
|
|
26
|
+
*/
|
|
27
|
+
import { fileURLToPath } from 'node:url';
|
|
28
|
+
import { createVurbTester } from '@vurb/testing';
|
|
29
|
+
import { autoDiscover } from '@vurb/core';
|
|
30
|
+
import { f } from '../src/vurb.js';
|
|
31
|
+
|
|
32
|
+
const registry = f.registry();
|
|
33
|
+
await autoDiscover(registry, fileURLToPath(new URL('../src/tools', import.meta.url)));
|
|
34
|
+
|
|
35
|
+
export const tester = createVurbTester(registry, {
|
|
36
|
+
contextFactory: () => ({
|
|
37
|
+
role: 'ADMIN' as const,
|
|
38
|
+
tenantId: 'test-tenant',
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
41
|
`;
|
|
42
42
|
}
|
|
43
43
|
/** Generate `tests/system.test.ts` — Egress Firewall + RBAC tests */
|
|
44
44
|
export function systemTestTs() {
|
|
45
|
-
return `/**
|
|
46
|
-
* System Tools — Egress Firewall & RBAC Tests
|
|
47
|
-
*
|
|
48
|
-
* Proves that:
|
|
49
|
-
* 1. The Presenter strips undeclared fields (SOC2 CC6.1)
|
|
50
|
-
* 2. RBAC middleware blocks GUEST access (SOC2 CC6.3)
|
|
51
|
-
* 3. System rules from .describe() are injected
|
|
52
|
-
*/
|
|
53
|
-
import { describe, it, expect } from 'vitest';
|
|
54
|
-
import { tester } from './setup.js';
|
|
55
|
-
|
|
56
|
-
describe('System Tools', () => {
|
|
57
|
-
describe('Egress Firewall', () => {
|
|
58
|
-
it('should return validated health data through the Presenter', async () => {
|
|
59
|
-
const result = await tester.callAction('system', 'health');
|
|
60
|
-
|
|
61
|
-
expect(result.isError).toBe(false);
|
|
62
|
-
expect(result.data).toHaveProperty('status');
|
|
63
|
-
expect(result.data).toHaveProperty('uptime');
|
|
64
|
-
expect(result.data).toHaveProperty('version');
|
|
65
|
-
expect(result.data).toHaveProperty('timestamp');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should strip undeclared fields (tenant must NOT leak)', async () => {
|
|
69
|
-
const result = await tester.callAction('system', 'health');
|
|
70
|
-
|
|
71
|
-
expect(result.isError).toBe(false);
|
|
72
|
-
// The handler returns 'tenant' but the Presenter schema
|
|
73
|
-
// does not declare it → stripped by Egress Firewall
|
|
74
|
-
expect(result.data).not.toHaveProperty('tenant');
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should include JIT system rules from .describe()', async () => {
|
|
78
|
-
const result = await tester.callAction('system', 'health');
|
|
79
|
-
|
|
80
|
-
expect(result.systemRules.length).toBeGreaterThan(0);
|
|
81
|
-
expect(result.systemRules.some(
|
|
82
|
-
(r: string) => r.includes('uptime') || r.includes('Uptime')
|
|
83
|
-
)).toBe(true);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('Echo Tool', () => {
|
|
88
|
-
it('should echo the message back', async () => {
|
|
89
|
-
const result = await tester.callAction('system', 'echo', {
|
|
90
|
-
message: 'hello vurb',
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(result.isError).toBe(false);
|
|
94
|
-
expect(result.data).toHaveProperty('echo', 'hello vurb');
|
|
95
|
-
expect(result.data).toHaveProperty('receivedAt');
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
});
|
|
45
|
+
return `/**
|
|
46
|
+
* System Tools — Egress Firewall & RBAC Tests
|
|
47
|
+
*
|
|
48
|
+
* Proves that:
|
|
49
|
+
* 1. The Presenter strips undeclared fields (SOC2 CC6.1)
|
|
50
|
+
* 2. RBAC middleware blocks GUEST access (SOC2 CC6.3)
|
|
51
|
+
* 3. System rules from .describe() are injected
|
|
52
|
+
*/
|
|
53
|
+
import { describe, it, expect } from 'vitest';
|
|
54
|
+
import { tester } from './setup.js';
|
|
55
|
+
|
|
56
|
+
describe('System Tools', () => {
|
|
57
|
+
describe('Egress Firewall', () => {
|
|
58
|
+
it('should return validated health data through the Presenter', async () => {
|
|
59
|
+
const result = await tester.callAction('system', 'health');
|
|
60
|
+
|
|
61
|
+
expect(result.isError).toBe(false);
|
|
62
|
+
expect(result.data).toHaveProperty('status');
|
|
63
|
+
expect(result.data).toHaveProperty('uptime');
|
|
64
|
+
expect(result.data).toHaveProperty('version');
|
|
65
|
+
expect(result.data).toHaveProperty('timestamp');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should strip undeclared fields (tenant must NOT leak)', async () => {
|
|
69
|
+
const result = await tester.callAction('system', 'health');
|
|
70
|
+
|
|
71
|
+
expect(result.isError).toBe(false);
|
|
72
|
+
// The handler returns 'tenant' but the Presenter schema
|
|
73
|
+
// does not declare it → stripped by Egress Firewall
|
|
74
|
+
expect(result.data).not.toHaveProperty('tenant');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should include JIT system rules from .describe()', async () => {
|
|
78
|
+
const result = await tester.callAction('system', 'health');
|
|
79
|
+
|
|
80
|
+
expect(result.systemRules.length).toBeGreaterThan(0);
|
|
81
|
+
expect(result.systemRules.some(
|
|
82
|
+
(r: string) => r.includes('uptime') || r.includes('Uptime')
|
|
83
|
+
)).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('Echo Tool', () => {
|
|
88
|
+
it('should echo the message back', async () => {
|
|
89
|
+
const result = await tester.callAction('system', 'echo', {
|
|
90
|
+
message: 'hello vurb',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(result.isError).toBe(false);
|
|
94
|
+
expect(result.data).toHaveProperty('echo', 'hello vurb');
|
|
95
|
+
expect(result.data).toHaveProperty('receivedAt');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
99
|
`;
|
|
100
100
|
}
|
|
101
101
|
//# sourceMappingURL=testing.js.map
|
|
@@ -8,56 +8,56 @@
|
|
|
8
8
|
*/
|
|
9
9
|
/** Generate `src/tools/system/health.ts` — Health check with Presenter */
|
|
10
10
|
export function healthToolTs() {
|
|
11
|
-
return `/**
|
|
12
|
-
* System Health Tool — Full MVA Pipeline (Fluent API)
|
|
13
|
-
*
|
|
14
|
-
* Demonstrates:
|
|
15
|
-
* - f.query() — read-only semantic verb (auto-sets readOnlyHint)
|
|
16
|
-
* - .describe() — LLM-facing description
|
|
17
|
-
* - .returns() — Presenter (Egress Firewall + system rules + UI)
|
|
18
|
-
* - .handle(input, ctx) — fully typed handler
|
|
19
|
-
* - export default for autoDiscover()
|
|
20
|
-
*/
|
|
21
|
-
import { f } from '../../vurb.js';
|
|
22
|
-
import { SystemPresenter } from '../../presenters/SystemPresenter.js';
|
|
23
|
-
|
|
24
|
-
export default f.query('system.health')
|
|
25
|
-
.describe('Real-time server health status')
|
|
26
|
-
.returns(SystemPresenter)
|
|
27
|
-
.handle(async (_input, ctx) => {
|
|
28
|
-
// Return raw data — the Presenter validates, strips
|
|
29
|
-
// undeclared fields, injects rules, and renders UI.
|
|
30
|
-
return {
|
|
31
|
-
status: 'healthy',
|
|
32
|
-
uptime: process.uptime(),
|
|
33
|
-
version: '0.1.0',
|
|
34
|
-
timestamp: new Date().toISOString(),
|
|
35
|
-
tenant: ctx.tenantId,
|
|
36
|
-
};
|
|
37
|
-
});
|
|
11
|
+
return `/**
|
|
12
|
+
* System Health Tool — Full MVA Pipeline (Fluent API)
|
|
13
|
+
*
|
|
14
|
+
* Demonstrates:
|
|
15
|
+
* - f.query() — read-only semantic verb (auto-sets readOnlyHint)
|
|
16
|
+
* - .describe() — LLM-facing description
|
|
17
|
+
* - .returns() — Presenter (Egress Firewall + system rules + UI)
|
|
18
|
+
* - .handle(input, ctx) — fully typed handler
|
|
19
|
+
* - export default for autoDiscover()
|
|
20
|
+
*/
|
|
21
|
+
import { f } from '../../vurb.js';
|
|
22
|
+
import { SystemPresenter } from '../../presenters/SystemPresenter.js';
|
|
23
|
+
|
|
24
|
+
export default f.query('system.health')
|
|
25
|
+
.describe('Real-time server health status')
|
|
26
|
+
.returns(SystemPresenter)
|
|
27
|
+
.handle(async (_input, ctx) => {
|
|
28
|
+
// Return raw data — the Presenter validates, strips
|
|
29
|
+
// undeclared fields, injects rules, and renders UI.
|
|
30
|
+
return {
|
|
31
|
+
status: 'healthy',
|
|
32
|
+
uptime: process.uptime(),
|
|
33
|
+
version: '0.1.0',
|
|
34
|
+
timestamp: new Date().toISOString(),
|
|
35
|
+
tenant: ctx.tenantId,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
38
|
`;
|
|
39
39
|
}
|
|
40
40
|
/** Generate `src/tools/system/echo.ts` — Simple echo tool */
|
|
41
41
|
export function echoToolTs() {
|
|
42
|
-
return `/**
|
|
43
|
-
* Echo Tool — Connectivity Testing (Fluent API)
|
|
44
|
-
*
|
|
45
|
-
* Demonstrates:
|
|
46
|
-
* - f.query() with .withString() typed parameter
|
|
47
|
-
* - .handle(input, ctx) — input.message is typed as string
|
|
48
|
-
* - Implicit success() wrapping — return raw data, framework wraps it
|
|
49
|
-
*/
|
|
50
|
-
import { f } from '../../vurb.js';
|
|
51
|
-
|
|
52
|
-
export default f.query('system.echo')
|
|
53
|
-
.describe('Echo a message back (connectivity test)')
|
|
54
|
-
.withString('message', 'Message to echo back')
|
|
55
|
-
.handle(async (input) => {
|
|
56
|
-
return {
|
|
57
|
-
echo: input['message'],
|
|
58
|
-
receivedAt: new Date().toISOString(),
|
|
59
|
-
};
|
|
60
|
-
});
|
|
42
|
+
return `/**
|
|
43
|
+
* Echo Tool — Connectivity Testing (Fluent API)
|
|
44
|
+
*
|
|
45
|
+
* Demonstrates:
|
|
46
|
+
* - f.query() with .withString() typed parameter
|
|
47
|
+
* - .handle(input, ctx) — input.message is typed as string
|
|
48
|
+
* - Implicit success() wrapping — return raw data, framework wraps it
|
|
49
|
+
*/
|
|
50
|
+
import { f } from '../../vurb.js';
|
|
51
|
+
|
|
52
|
+
export default f.query('system.echo')
|
|
53
|
+
.describe('Echo a message back (connectivity test)')
|
|
54
|
+
.withString('message', 'Message to echo back')
|
|
55
|
+
.handle(async (input) => {
|
|
56
|
+
return {
|
|
57
|
+
echo: input['message'],
|
|
58
|
+
receivedAt: new Date().toISOString(),
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
61
|
`;
|
|
62
62
|
}
|
|
63
63
|
//# sourceMappingURL=tools.js.map
|