@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.
Files changed (107) hide show
  1. package/README.md +677 -677
  2. package/dist/cli/constants.js +59 -59
  3. package/dist/cli/templates/config.js +26 -26
  4. package/dist/cli/templates/constants.d.ts +1 -1
  5. package/dist/cli/templates/constants.d.ts.map +1 -1
  6. package/dist/cli/templates/constants.js +1 -1
  7. package/dist/cli/templates/constants.js.map +1 -1
  8. package/dist/cli/templates/core.d.ts.map +1 -1
  9. package/dist/cli/templates/core.js +96 -169
  10. package/dist/cli/templates/core.js.map +1 -1
  11. package/dist/cli/templates/middleware.js +25 -25
  12. package/dist/cli/templates/readme.js +142 -142
  13. package/dist/cli/templates/testing.js +84 -84
  14. package/dist/cli/templates/tools.js +46 -46
  15. package/dist/cli/templates/vectors/database.js +69 -69
  16. package/dist/cli/templates/vectors/oauth.js +63 -63
  17. package/dist/cli/templates/vectors/openapi.js +97 -97
  18. package/dist/core/middleware/AuditTrail.d.ts +128 -0
  19. package/dist/core/middleware/AuditTrail.d.ts.map +1 -0
  20. package/dist/core/middleware/AuditTrail.js +94 -0
  21. package/dist/core/middleware/AuditTrail.js.map +1 -0
  22. package/dist/core/middleware/InputFirewall.d.ts +95 -0
  23. package/dist/core/middleware/InputFirewall.d.ts.map +1 -0
  24. package/dist/core/middleware/InputFirewall.js +104 -0
  25. package/dist/core/middleware/InputFirewall.js.map +1 -0
  26. package/dist/core/middleware/RateLimiter.d.ts +151 -0
  27. package/dist/core/middleware/RateLimiter.d.ts.map +1 -0
  28. package/dist/core/middleware/RateLimiter.js +121 -0
  29. package/dist/core/middleware/RateLimiter.js.map +1 -0
  30. package/dist/core/middleware/index.d.ts +6 -0
  31. package/dist/core/middleware/index.d.ts.map +1 -1
  32. package/dist/core/middleware/index.js +4 -0
  33. package/dist/core/middleware/index.js.map +1 -1
  34. package/dist/index.d.ts +28 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +15 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/introspection/SemanticProbe.js +49 -49
  39. package/dist/observability/TelemetryEvent.d.ts +61 -1
  40. package/dist/observability/TelemetryEvent.d.ts.map +1 -1
  41. package/dist/presenter/JudgeChain.d.ts +129 -0
  42. package/dist/presenter/JudgeChain.d.ts.map +1 -0
  43. package/dist/presenter/JudgeChain.js +215 -0
  44. package/dist/presenter/JudgeChain.js.map +1 -0
  45. package/dist/presenter/PostProcessor.d.ts.map +1 -1
  46. package/dist/presenter/PostProcessor.js +11 -66
  47. package/dist/presenter/PostProcessor.js.map +1 -1
  48. package/dist/presenter/Presenter.d.ts +175 -37
  49. package/dist/presenter/Presenter.d.ts.map +1 -1
  50. package/dist/presenter/Presenter.js +265 -154
  51. package/dist/presenter/Presenter.js.map +1 -1
  52. package/dist/presenter/PresenterPipeline.d.ts +147 -0
  53. package/dist/presenter/PresenterPipeline.d.ts.map +1 -0
  54. package/dist/presenter/PresenterPipeline.js +271 -0
  55. package/dist/presenter/PresenterPipeline.js.map +1 -0
  56. package/dist/presenter/PromptFirewall.d.ts +160 -0
  57. package/dist/presenter/PromptFirewall.d.ts.map +1 -0
  58. package/dist/presenter/PromptFirewall.js +228 -0
  59. package/dist/presenter/PromptFirewall.js.map +1 -0
  60. package/dist/presenter/ResponseBuilder.d.ts +13 -0
  61. package/dist/presenter/ResponseBuilder.d.ts.map +1 -1
  62. package/dist/presenter/ResponseBuilder.js +28 -1
  63. package/dist/presenter/ResponseBuilder.js.map +1 -1
  64. package/dist/presenter/TelemetryCollector.d.ts +48 -0
  65. package/dist/presenter/TelemetryCollector.d.ts.map +1 -0
  66. package/dist/presenter/TelemetryCollector.js +93 -0
  67. package/dist/presenter/TelemetryCollector.js.map +1 -0
  68. package/dist/presenter/definePresenter.d.ts +112 -0
  69. package/dist/presenter/definePresenter.d.ts.map +1 -1
  70. package/dist/presenter/definePresenter.js +110 -0
  71. package/dist/presenter/definePresenter.js.map +1 -1
  72. package/dist/presenter/index.d.ts +6 -2
  73. package/dist/presenter/index.d.ts.map +1 -1
  74. package/dist/presenter/index.js +5 -1
  75. package/dist/presenter/index.js.map +1 -1
  76. package/dist/presenter/ui.d.ts +31 -8
  77. package/dist/presenter/ui.d.ts.map +1 -1
  78. package/dist/presenter/ui.js +16 -16
  79. package/dist/presenter/ui.js.map +1 -1
  80. package/dist/prompt/FluentPromptBuilder.d.ts.map +1 -1
  81. package/dist/resource/ResourceBuilder.d.ts +129 -0
  82. package/dist/resource/ResourceBuilder.d.ts.map +1 -0
  83. package/dist/resource/ResourceBuilder.js +93 -0
  84. package/dist/resource/ResourceBuilder.js.map +1 -0
  85. package/dist/resource/ResourceRegistry.d.ts +147 -0
  86. package/dist/resource/ResourceRegistry.d.ts.map +1 -0
  87. package/dist/resource/ResourceRegistry.js +234 -0
  88. package/dist/resource/ResourceRegistry.js.map +1 -0
  89. package/dist/resource/SubscriptionManager.d.ts +67 -0
  90. package/dist/resource/SubscriptionManager.d.ts.map +1 -0
  91. package/dist/resource/SubscriptionManager.js +86 -0
  92. package/dist/resource/SubscriptionManager.js.map +1 -0
  93. package/dist/resource/index.d.ts +13 -0
  94. package/dist/resource/index.d.ts.map +1 -0
  95. package/dist/resource/index.js +13 -0
  96. package/dist/resource/index.js.map +1 -0
  97. package/dist/server/ServerAttachment.d.ts +26 -0
  98. package/dist/server/ServerAttachment.d.ts.map +1 -1
  99. package/dist/server/ServerAttachment.js +70 -2
  100. package/dist/server/ServerAttachment.js.map +1 -1
  101. package/dist/server/index.d.ts +1 -1
  102. package/dist/server/index.d.ts.map +1 -1
  103. package/dist/server/startServer.d.ts +22 -1
  104. package/dist/server/startServer.d.ts.map +1 -1
  105. package/dist/server/startServer.js +98 -5
  106. package/dist/server/startServer.js.map +1 -1
  107. package/package.json +1 -1
@@ -0,0 +1,147 @@
1
+ /**
2
+ * PresenterPipeline — Decomposed Make Pipeline
3
+ *
4
+ * Extracted from `Presenter.make()` to uphold SRP and enable isolated testing.
5
+ * Each step is a pure function that receives a `PresenterSnapshot` (read-only
6
+ * config) and produces side-effects on a `ResponseBuilder`.
7
+ *
8
+ * The `executePipeline()` orchestrator replaces the inline logic previously
9
+ * in `Presenter.make()`, maintaining the exact same behavior and output.
10
+ *
11
+ * @internal
12
+ * @module
13
+ */
14
+ import { ZodType } from 'zod';
15
+ import { ResponseBuilder } from './ResponseBuilder.js';
16
+ import { type UiBlock } from './ui.js';
17
+ import { type ActionSuggestion } from './Presenter.js';
18
+ import { type RedactConfig, type RedactFn } from './RedactEngine.js';
19
+ import { type StringifyFn } from '../core/serialization/JsonSerializer.js';
20
+ import { type Presenter } from './Presenter.js';
21
+ /** Static rules (string array) OR dynamic rules with context (function) */
22
+ export type RulesConfig<T> = readonly string[] | ((data: T, ctx?: unknown) => (string | null)[]);
23
+ /** Collection-level rules — static or dynamic */
24
+ export type CollectionRulesFn<T> = readonly string[] | ((items: T[], ctx?: unknown) => (string | null)[]);
25
+ /** UI blocks callback — with optional context */
26
+ export type ItemUiBlocksFn<T> = (item: T, ctx?: unknown) => (UiBlock | null)[];
27
+ /** Collection UI blocks callback — with optional context */
28
+ export type CollectionUiBlocksFn<T> = (items: T[], ctx?: unknown) => (UiBlock | null)[];
29
+ /** Suggest actions callback — with optional context */
30
+ export type SuggestActionsFn<T> = (data: T, ctx?: unknown) => ActionSuggestion[];
31
+ /** Collection-level suggest actions callback */
32
+ export type CollectionSuggestActionsFn<T> = (items: T[], ctx?: unknown) => (ActionSuggestion | null)[];
33
+ /** Agent limit configuration */
34
+ export interface AgentLimitConfig {
35
+ readonly max: number;
36
+ readonly onTruncate: (omittedCount: number) => UiBlock;
37
+ }
38
+ /** An embedded child Presenter for relational composition */
39
+ export interface EmbedEntry {
40
+ readonly key: string;
41
+ readonly presenter: Presenter<unknown>;
42
+ }
43
+ /**
44
+ * Read-only snapshot of Presenter configuration for the pipeline.
45
+ *
46
+ * Created by `Presenter._toSnapshot()` on each `make()` call.
47
+ * Avoids exposing private state while enabling standalone step functions.
48
+ *
49
+ * @typeParam T - The validated output type
50
+ * @internal
51
+ */
52
+ export interface PresenterSnapshot<T> {
53
+ readonly name: string;
54
+ readonly schema?: ZodType<any, any, any> | undefined;
55
+ readonly rules: RulesConfig<T>;
56
+ readonly collectionRules: CollectionRulesFn<T>;
57
+ readonly itemUiBlocks?: ItemUiBlocksFn<T> | undefined;
58
+ readonly collectionUiBlocks?: CollectionUiBlocksFn<T> | undefined;
59
+ readonly suggestActions?: SuggestActionsFn<T> | undefined;
60
+ readonly collectionSuggestActions?: CollectionSuggestActionsFn<T> | undefined;
61
+ readonly agentLimit?: AgentLimitConfig | undefined;
62
+ readonly embeds: readonly EmbedEntry[];
63
+ readonly redactConfig?: RedactConfig | undefined;
64
+ readonly compiledStringify?: StringifyFn | undefined;
65
+ /** Mutable: may be lazily compiled */
66
+ compiledRedactor?: RedactFn | undefined;
67
+ }
68
+ /**
69
+ * Step 0: Cognitive Guardrails — truncate array by agentLimit.
70
+ *
71
+ * If the data is an array larger than the configured limit, it is sliced
72
+ * and a truncation UiBlock is returned for insertion.
73
+ *
74
+ * @returns Potentially truncated data + optional truncation UiBlock
75
+ * @internal
76
+ */
77
+ export declare function stepTruncate<T>(data: T | T[], isArray: boolean, snapshot: PresenterSnapshot<T>): {
78
+ data: T | T[];
79
+ truncationBlock?: UiBlock | undefined;
80
+ };
81
+ /**
82
+ * Step 1: Validate data through the Zod schema (if configured).
83
+ * For arrays, each item is validated independently.
84
+ *
85
+ * @throws {PresenterValidationError} on schema mismatch
86
+ * @internal
87
+ */
88
+ export declare function stepValidate<T>(data: T | T[], isArray: boolean, snapshot: PresenterSnapshot<T>): T | T[];
89
+ /**
90
+ * Step 2: Apply PII redaction to wire-facing data.
91
+ * Creates a deep clone to preserve original data for UI/rules.
92
+ *
93
+ * @internal
94
+ */
95
+ export declare function stepRedact<T>(data: T | T[], isArray: boolean, snapshot: PresenterSnapshot<T>): T | T[];
96
+ /**
97
+ * Step 3: Generate and attach UI blocks to the response builder.
98
+ * Auto-detects single vs collection. Filters `null` blocks.
99
+ *
100
+ * @internal
101
+ */
102
+ export declare function stepUiBlocks<T>(builder: ResponseBuilder, data: T | T[], isArray: boolean, snapshot: PresenterSnapshot<T>, ctx?: unknown): void;
103
+ /**
104
+ * Step 4: Resolve and attach domain rules to the response builder.
105
+ * Supports both static arrays and dynamic context-aware functions.
106
+ *
107
+ * For collections: also evaluates `collectionRules` (if defined) and
108
+ * merges them after per-item rules.
109
+ *
110
+ * @internal
111
+ */
112
+ export declare function stepRules<T>(builder: ResponseBuilder, data: T | T[], isArray: boolean, snapshot: PresenterSnapshot<T>, ctx?: unknown): void;
113
+ /**
114
+ * Step 5: Evaluate and attach action suggestions to the response.
115
+ *
116
+ * For collections: uses `collectionSuggestActions` if defined,
117
+ * otherwise falls back to per-item evaluation on the first item.
118
+ *
119
+ * @internal
120
+ */
121
+ export declare function stepSuggestions<T>(builder: ResponseBuilder, data: T | T[], isArray: boolean, snapshot: PresenterSnapshot<T>, ctx?: unknown): void;
122
+ /**
123
+ * Step 6: Process embedded child Presenters for nested relational data.
124
+ * Merges child UI blocks and rules into the parent builder.
125
+ *
126
+ * For collections: iterates all array items. Rules are deduplicated
127
+ * via a Set to avoid repetition. UI blocks are emitted only for the
128
+ * first item to prevent context window explosion.
129
+ *
130
+ * @internal
131
+ */
132
+ export declare function stepEmbeds<T>(builder: ResponseBuilder, data: T | T[], isArray: boolean, snapshot: PresenterSnapshot<T>, ctx?: unknown): void;
133
+ /**
134
+ * Execute the full Presenter pipeline.
135
+ *
136
+ * Orchestrates: truncate → validate → embed → render UI → attach rules
137
+ * → suggest actions → **Late Guillotine** (`_select` filter).
138
+ *
139
+ * @param data - Raw data from handler
140
+ * @param snapshot - Read-only configuration snapshot
141
+ * @param ctx - Optional request context
142
+ * @param selectFields - Optional field names for context window optimization
143
+ * @returns A fully-composed ResponseBuilder
144
+ * @internal
145
+ */
146
+ export declare function executePipeline<T>(data: T | T[], snapshot: PresenterSnapshot<T>, ctx?: unknown, selectFields?: string[]): ResponseBuilder;
147
+ //# sourceMappingURL=PresenterPipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PresenterPipeline.d.ts","sourceRoot":"","sources":["../../src/presenter/PresenterPipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,271 @@
1
+ /**
2
+ * PresenterPipeline — Decomposed Make Pipeline
3
+ *
4
+ * Extracted from `Presenter.make()` to uphold SRP and enable isolated testing.
5
+ * Each step is a pure function that receives a `PresenterSnapshot` (read-only
6
+ * config) and produces side-effects on a `ResponseBuilder`.
7
+ *
8
+ * The `executePipeline()` orchestrator replaces the inline logic previously
9
+ * in `Presenter.make()`, maintaining the exact same behavior and output.
10
+ *
11
+ * @internal
12
+ * @module
13
+ */
14
+ import { ZodType, ZodError } from 'zod';
15
+ import { ResponseBuilder } from './ResponseBuilder.js';
16
+ import {} from './ui.js';
17
+ import {} from './Presenter.js';
18
+ import { PresenterValidationError } from './PresenterValidationError.js';
19
+ import { applySelectFilter } from './SelectUtils.js';
20
+ import { compileRedactor } from './RedactEngine.js';
21
+ import {} from '../core/serialization/JsonSerializer.js';
22
+ import {} from './Presenter.js';
23
+ // ── Step Functions ──────────────────────────────────────
24
+ /**
25
+ * Step 0: Cognitive Guardrails — truncate array by agentLimit.
26
+ *
27
+ * If the data is an array larger than the configured limit, it is sliced
28
+ * and a truncation UiBlock is returned for insertion.
29
+ *
30
+ * @returns Potentially truncated data + optional truncation UiBlock
31
+ * @internal
32
+ */
33
+ export function stepTruncate(data, isArray, snapshot) {
34
+ if (isArray && snapshot.agentLimit && data.length > snapshot.agentLimit.max) {
35
+ const fullLength = data.length;
36
+ const omitted = fullLength - snapshot.agentLimit.max;
37
+ return {
38
+ data: data.slice(0, snapshot.agentLimit.max),
39
+ truncationBlock: snapshot.agentLimit.onTruncate(omitted),
40
+ };
41
+ }
42
+ return { data };
43
+ }
44
+ /**
45
+ * Step 1: Validate data through the Zod schema (if configured).
46
+ * For arrays, each item is validated independently.
47
+ *
48
+ * @throws {PresenterValidationError} on schema mismatch
49
+ * @internal
50
+ */
51
+ export function stepValidate(data, isArray, snapshot) {
52
+ if (!snapshot.schema)
53
+ return data;
54
+ try {
55
+ if (isArray) {
56
+ return data.map(item => snapshot.schema.parse(item));
57
+ }
58
+ return snapshot.schema.parse(data);
59
+ }
60
+ catch (err) {
61
+ if (err instanceof ZodError) {
62
+ throw new PresenterValidationError(snapshot.name, err);
63
+ }
64
+ throw err;
65
+ }
66
+ }
67
+ /**
68
+ * Step 2: Apply PII redaction to wire-facing data.
69
+ * Creates a deep clone to preserve original data for UI/rules.
70
+ *
71
+ * @internal
72
+ */
73
+ export function stepRedact(data, isArray, snapshot) {
74
+ // Lazy recompilation: if redactPII was called before fast-redact loaded
75
+ if (!snapshot.compiledRedactor && snapshot.redactConfig) {
76
+ snapshot.compiledRedactor = compileRedactor(snapshot.redactConfig);
77
+ if (!snapshot.compiledRedactor) {
78
+ console.warn(`[vurb] Presenter "${snapshot.name}": PII redaction configured but fast-redact is not available. ` +
79
+ `Data will pass through WITHOUT redaction. Ensure initVurb() completes before .make() is called, ` +
80
+ `or install fast-redact as a dependency.`);
81
+ }
82
+ }
83
+ if (!snapshot.compiledRedactor)
84
+ return data;
85
+ if (isArray) {
86
+ return data.map(item => snapshot.compiledRedactor(item));
87
+ }
88
+ return snapshot.compiledRedactor(data);
89
+ }
90
+ /**
91
+ * Step 3: Generate and attach UI blocks to the response builder.
92
+ * Auto-detects single vs collection. Filters `null` blocks.
93
+ *
94
+ * @internal
95
+ */
96
+ export function stepUiBlocks(builder, data, isArray, snapshot, ctx) {
97
+ if (isArray && snapshot.collectionUiBlocks) {
98
+ const blocks = snapshot.collectionUiBlocks(data, ctx).filter(Boolean);
99
+ if (blocks.length > 0)
100
+ builder.uiBlocks(blocks);
101
+ }
102
+ else if (!isArray && snapshot.itemUiBlocks) {
103
+ const blocks = snapshot.itemUiBlocks(data, ctx).filter(Boolean);
104
+ if (blocks.length > 0)
105
+ builder.uiBlocks(blocks);
106
+ }
107
+ }
108
+ /**
109
+ * Step 4: Resolve and attach domain rules to the response builder.
110
+ * Supports both static arrays and dynamic context-aware functions.
111
+ *
112
+ * For collections: also evaluates `collectionRules` (if defined) and
113
+ * merges them after per-item rules.
114
+ *
115
+ * @internal
116
+ */
117
+ export function stepRules(builder, data, isArray, snapshot, ctx) {
118
+ // Per-item rules
119
+ if (typeof snapshot.rules === 'function') {
120
+ const singleData = isArray ? data[0] : data;
121
+ if (singleData !== undefined) {
122
+ const resolved = snapshot.rules(singleData, ctx)
123
+ .filter((r) => r !== null);
124
+ if (resolved.length > 0)
125
+ builder.systemRules(resolved);
126
+ }
127
+ }
128
+ else if (snapshot.rules.length > 0) {
129
+ builder.systemRules(snapshot.rules);
130
+ }
131
+ // Collection-level rules (additive — appended after per-item rules)
132
+ const hasCollectionRules = typeof snapshot.collectionRules === 'function'
133
+ || snapshot.collectionRules.length > 0;
134
+ if (isArray && hasCollectionRules) {
135
+ const items = data;
136
+ if (typeof snapshot.collectionRules === 'function') {
137
+ const resolved = snapshot.collectionRules(items, ctx)
138
+ .filter((r) => r !== null);
139
+ if (resolved.length > 0)
140
+ builder.systemRules(resolved);
141
+ }
142
+ else if (snapshot.collectionRules.length > 0) {
143
+ builder.systemRules(snapshot.collectionRules);
144
+ }
145
+ }
146
+ }
147
+ /**
148
+ * Step 5: Evaluate and attach action suggestions to the response.
149
+ *
150
+ * For collections: uses `collectionSuggestActions` if defined,
151
+ * otherwise falls back to per-item evaluation on the first item.
152
+ *
153
+ * @internal
154
+ */
155
+ export function stepSuggestions(builder, data, isArray, snapshot, ctx) {
156
+ // Collection-level suggestions (preferred for arrays)
157
+ if (isArray && snapshot.collectionSuggestActions) {
158
+ const items = data;
159
+ if (items.length === 0)
160
+ return;
161
+ const suggestions = snapshot.collectionSuggestActions(items, ctx)
162
+ .filter((s) => s !== null);
163
+ if (suggestions.length > 0) {
164
+ builder.systemHint(suggestions);
165
+ }
166
+ return;
167
+ }
168
+ // Per-item fallback (single item or first item of array)
169
+ if (!snapshot.suggestActions)
170
+ return;
171
+ const singleData = isArray ? data[0] : data;
172
+ if (singleData === undefined)
173
+ return;
174
+ const suggestions = snapshot.suggestActions(singleData, ctx);
175
+ if (suggestions.length > 0) {
176
+ builder.systemHint(suggestions);
177
+ }
178
+ }
179
+ /**
180
+ * Step 6: Process embedded child Presenters for nested relational data.
181
+ * Merges child UI blocks and rules into the parent builder.
182
+ *
183
+ * For collections: iterates all array items. Rules are deduplicated
184
+ * via a Set to avoid repetition. UI blocks are emitted only for the
185
+ * first item to prevent context window explosion.
186
+ *
187
+ * @internal
188
+ */
189
+ export function stepEmbeds(builder, data, isArray, snapshot, ctx) {
190
+ if (snapshot.embeds.length === 0)
191
+ return;
192
+ const items = isArray
193
+ ? data.filter((item) => item !== undefined && typeof item === 'object')
194
+ : [data].filter((item) => item !== undefined && typeof item === 'object');
195
+ if (items.length === 0)
196
+ return;
197
+ // Track which rule blocks we've already emitted (dedup for arrays)
198
+ const emittedRules = new Set();
199
+ for (let itemIdx = 0; itemIdx < items.length; itemIdx++) {
200
+ const item = items[itemIdx];
201
+ for (const embed of snapshot.embeds) {
202
+ const nestedData = item[embed.key];
203
+ if (nestedData === undefined || nestedData === null)
204
+ continue;
205
+ const childBuilder = embed.presenter.make(nestedData, ctx);
206
+ const childResponse = childBuilder.build();
207
+ // Skip the first block (data) — parent already has it
208
+ for (let i = 1; i < childResponse.content.length; i++) {
209
+ const blockText = childResponse.content[i].text;
210
+ // For arrays: deduplicate rule/hint blocks, emit UI only for first item
211
+ if (isArray && itemIdx > 0) {
212
+ if (emittedRules.has(blockText))
213
+ continue;
214
+ if (blockText.includes('<ui_passthrough'))
215
+ continue;
216
+ }
217
+ emittedRules.add(blockText);
218
+ builder.rawBlock(blockText);
219
+ }
220
+ }
221
+ }
222
+ }
223
+ // ── Pipeline Orchestrator ───────────────────────────────
224
+ /**
225
+ * Execute the full Presenter pipeline.
226
+ *
227
+ * Orchestrates: truncate → validate → embed → render UI → attach rules
228
+ * → suggest actions → **Late Guillotine** (`_select` filter).
229
+ *
230
+ * @param data - Raw data from handler
231
+ * @param snapshot - Read-only configuration snapshot
232
+ * @param ctx - Optional request context
233
+ * @param selectFields - Optional field names for context window optimization
234
+ * @returns A fully-composed ResponseBuilder
235
+ * @internal
236
+ */
237
+ export function executePipeline(data, snapshot, ctx, selectFields) {
238
+ const isArray = Array.isArray(data);
239
+ // Step 0: Cognitive Guardrails — truncate if needed
240
+ const truncated = stepTruncate(data, isArray, snapshot);
241
+ data = truncated.data;
242
+ // Step 1: Process embedded child Presenters (on RAW data, before validation)
243
+ const rawForEmbeds = data;
244
+ // Step 2: Validate — produces the FULL validated data
245
+ const validated = stepValidate(data, isArray, snapshot);
246
+ // ── Late Guillotine ──────────────────────────────────
247
+ // Steps 3-6 use the FULL validated data so that UI blocks,
248
+ // system rules, and action suggestions never see undefined
249
+ // for pruned fields.
250
+ // Step 3: Determine wire-facing data (filtered or full)
251
+ const wireData = (selectFields && selectFields.length > 0)
252
+ ? applySelectFilter(validated, selectFields, isArray)
253
+ : validated;
254
+ // Step 3.1: DLP Redaction — mask PII on the wire-facing data
255
+ const safeWireData = stepRedact(wireData, isArray, snapshot);
256
+ const builder = new ResponseBuilder(safeWireData, snapshot.compiledStringify);
257
+ // Step 3.5: Truncation warning (first UI block, before all others)
258
+ if (truncated.truncationBlock) {
259
+ builder.uiBlock(truncated.truncationBlock);
260
+ }
261
+ // Step 4: Merge embedded child Presenter blocks (using FULL data)
262
+ stepEmbeds(builder, rawForEmbeds, isArray, snapshot, ctx);
263
+ // Step 5: Attach UI blocks (using FULL validated data)
264
+ stepUiBlocks(builder, validated, isArray, snapshot, ctx);
265
+ // Step 6: Attach rules (using FULL validated data)
266
+ stepRules(builder, validated, isArray, snapshot, ctx);
267
+ // Step 7: Attach action suggestions (using FULL validated data)
268
+ stepSuggestions(builder, validated, isArray, snapshot, ctx);
269
+ return builder;
270
+ }
271
+ //# sourceMappingURL=PresenterPipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PresenterPipeline.js","sourceRoot":"","sources":["../../src/presenter/PresenterPipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * PromptFirewall — LLM-as-Judge Output Protection
3
+ *
4
+ * Evaluates dynamically-generated system rules via a {@link JudgeChain}
5
+ * before they reach the LLM as `<domain_rules>`. This prevents prompt
6
+ * injection attacks where tainted data (e.g., user input stored in a
7
+ * database) is interpolated into system rules.
8
+ *
9
+ * The firewall operates inside `Presenter.makeAsync()`, AFTER all sync
10
+ * and async rules have been resolved. This means:
11
+ * - `executePipeline()` is NOT modified (zero async ripple)
12
+ * - `make()` throws if a firewall is configured (forces async path)
13
+ *
14
+ * **Design**: The framework provides the judge prompt via
15
+ * `buildFirewallPrompt()`. The developer only brings the LLM adapter(s).
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { createPresenter } from '@vurb/core';
20
+ *
21
+ * const InvoicePresenter = createPresenter('Invoice')
22
+ * .schema(invoiceSchema)
23
+ * .systemRules((inv) => [`Status: ${inv.description}`])
24
+ * .promptFirewall({
25
+ * adapter: { name: 'gpt-4o-mini', evaluate: (p) => openai.chat(p) },
26
+ * timeoutMs: 3000,
27
+ * });
28
+ *
29
+ * // MUST use makeAsync():
30
+ * return (await InvoicePresenter.makeAsync(data, ctx)).build();
31
+ * ```
32
+ *
33
+ * @module
34
+ */
35
+ import type { SemanticProbeAdapter } from '../introspection/SemanticProbe.js';
36
+ import type { TelemetrySink } from '../observability/TelemetryEvent.js';
37
+ import { type JudgeChain, type JudgeChainResult } from './JudgeChain.js';
38
+ /**
39
+ * Configuration for the PromptFirewall.
40
+ *
41
+ * Accepts either a single adapter or a pre-built JudgeChain for
42
+ * multi-adapter evaluation (fallback/consensus).
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * // Single adapter:
47
+ * .promptFirewall({ adapter: gptMini })
48
+ *
49
+ * // Multi-adapter (fallback):
50
+ * .promptFirewall({
51
+ * chain: createJudgeChain({
52
+ * adapters: [gptMini, claudeHaiku],
53
+ * strategy: 'fallback',
54
+ * }),
55
+ * })
56
+ *
57
+ * // Multi-adapter (consensus — both must agree):
58
+ * .promptFirewall({
59
+ * chain: createJudgeChain({
60
+ * adapters: [gptMini, claudeHaiku],
61
+ * strategy: 'consensus',
62
+ * }),
63
+ * })
64
+ * ```
65
+ */
66
+ export interface PromptFirewallConfig {
67
+ /**
68
+ * Single LLM adapter for evaluation.
69
+ * Mutually exclusive with `chain`. If both provided, `chain` wins.
70
+ */
71
+ readonly adapter?: SemanticProbeAdapter;
72
+ /**
73
+ * Pre-built JudgeChain for multi-adapter evaluation.
74
+ * Takes precedence over `adapter` if both are set.
75
+ */
76
+ readonly chain?: JudgeChain;
77
+ /**
78
+ * Timeout per individual adapter call in milliseconds.
79
+ * Only used when `adapter` is set (JudgeChain manages its own timeouts).
80
+ *
81
+ * @default 5000
82
+ */
83
+ readonly timeoutMs?: number;
84
+ /**
85
+ * Behavior when ALL judges fail (timeout, error, unparseable).
86
+ *
87
+ * - `false` (default) — **Fail-closed**: rules are DROPPED.
88
+ * - `true` — **Fail-open**: rules PASS (use at your own risk).
89
+ *
90
+ * Only used when `adapter` is set. JudgeChain manages its own failOpen.
91
+ *
92
+ * @default false
93
+ */
94
+ readonly failOpen?: boolean;
95
+ /**
96
+ * Optional telemetry sink for `security.firewall` events.
97
+ * When provided, emits an event after every evaluation with
98
+ * verdict details (allowed/rejected counts, duration, fallback).
99
+ */
100
+ readonly telemetry?: TelemetrySink;
101
+ }
102
+ /**
103
+ * Structured result of a firewall evaluation.
104
+ *
105
+ * Contains both allowed and rejected rules with reasoning,
106
+ * enabling telemetry and audit trails.
107
+ */
108
+ export interface FirewallVerdict {
109
+ /** Rules that passed the firewall (safe to send to LLM) */
110
+ readonly allowed: readonly string[];
111
+ /** Rules that were rejected (stripped from the response) */
112
+ readonly rejected: readonly FirewallRejection[];
113
+ /** Whether the verdict was determined by failOpen/failClosed */
114
+ readonly fallbackTriggered: boolean;
115
+ /** Total evaluation duration in milliseconds */
116
+ readonly durationMs: number;
117
+ /** Raw chain result for telemetry */
118
+ readonly chainResult: JudgeChainResult;
119
+ }
120
+ /**
121
+ * A single rejected rule with the reason for rejection.
122
+ */
123
+ export interface FirewallRejection {
124
+ /** The rule string that was rejected */
125
+ readonly rule: string;
126
+ /** Reason for rejection (from the judge) */
127
+ readonly reason: string;
128
+ }
129
+ /**
130
+ * Build the evaluation prompt for the firewall judge.
131
+ *
132
+ * The prompt asks the LLM to evaluate whether any of the provided
133
+ * system rules appear to contain prompt injection attempts.
134
+ *
135
+ * @param rules - Array of system rules to evaluate
136
+ * @returns Complete evaluation prompt
137
+ */
138
+ export declare function buildFirewallPrompt(rules: readonly string[]): string;
139
+ /**
140
+ * Parse the firewall judge's response into a structured verdict.
141
+ *
142
+ * @param rules - Original rules array
143
+ * @param chainResult - Result from the JudgeChain
144
+ * @returns Structured {@link FirewallVerdict}
145
+ *
146
+ * @internal
147
+ */
148
+ export declare function parseFirewallVerdict(rules: readonly string[], chainResult: JudgeChainResult): FirewallVerdict;
149
+ /**
150
+ * Evaluate system rules through the firewall.
151
+ *
152
+ * Builds the judge prompt, sends it through the chain, and
153
+ * parses the response into a structured {@link FirewallVerdict}.
154
+ *
155
+ * @param rules - System rules to evaluate
156
+ * @param config - Firewall configuration
157
+ * @returns A structured verdict with allowed and rejected rules
158
+ */
159
+ export declare function evaluateRules(rules: readonly string[], config: PromptFirewallConfig): Promise<FirewallVerdict>;
160
+ //# sourceMappingURL=PromptFirewall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptFirewall.d.ts","sourceRoot":"","sources":["../../src/presenter/PromptFirewall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAEH,KAAK,UAAU,EAEf,KAAK,gBAAgB,EACxB,MAAM,iBAAiB,CAAC;AAIzB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAExC;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;CACtC;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAEpC,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAEhD,gEAAgE;IAChE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IAEpC,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,qCAAqC;IACrC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CAC3B;AAID;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAgCpE;AAID;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,WAAW,EAAE,gBAAgB,GAC9B,eAAe,CAsFjB;AAoCD;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAC/B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,oBAAoB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA6C1B"}