@bstockwelldev/prompt-guardrails-core 1.0.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.
Files changed (46) hide show
  1. package/README.md +79 -0
  2. package/dist/errors.d.ts +11 -0
  3. package/dist/errors.d.ts.map +1 -0
  4. package/dist/errors.js +10 -0
  5. package/dist/errors.js.map +1 -0
  6. package/dist/index.d.ts +20 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +19 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/input.d.ts +27 -0
  11. package/dist/input.d.ts.map +1 -0
  12. package/dist/input.js +85 -0
  13. package/dist/input.js.map +1 -0
  14. package/dist/middleware.d.ts +29 -0
  15. package/dist/middleware.d.ts.map +1 -0
  16. package/dist/middleware.js +31 -0
  17. package/dist/middleware.js.map +1 -0
  18. package/dist/output.d.ts +28 -0
  19. package/dist/output.d.ts.map +1 -0
  20. package/dist/output.js +111 -0
  21. package/dist/output.js.map +1 -0
  22. package/dist/policy.d.ts +28 -0
  23. package/dist/policy.d.ts.map +1 -0
  24. package/dist/policy.js +60 -0
  25. package/dist/policy.js.map +1 -0
  26. package/dist/prompt.d.ts +22 -0
  27. package/dist/prompt.d.ts.map +1 -0
  28. package/dist/prompt.js +34 -0
  29. package/dist/prompt.js.map +1 -0
  30. package/dist/runtime.d.ts +29 -0
  31. package/dist/runtime.d.ts.map +1 -0
  32. package/dist/runtime.js +144 -0
  33. package/dist/runtime.js.map +1 -0
  34. package/dist/schemas.d.ts +124 -0
  35. package/dist/schemas.d.ts.map +1 -0
  36. package/dist/schemas.js +25 -0
  37. package/dist/schemas.js.map +1 -0
  38. package/dist/telemetry.d.ts +20 -0
  39. package/dist/telemetry.d.ts.map +1 -0
  40. package/dist/telemetry.js +38 -0
  41. package/dist/telemetry.js.map +1 -0
  42. package/dist/types.d.ts +82 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +40 -0
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @bstockwelldev/prompt-guardrails-core
2
+
3
+ Stateless server-side prompt guardrails: policy, input/output validation, structured invocation, and privacy-safe telemetry.
4
+
5
+ ## Scope
6
+
7
+ **In scope:** Versioned prompt policy, input validation, structured prompt builders, output validation, JSON repair, telemetry contracts, refusal typing.
8
+
9
+ **Out of scope:** React, Next.js routes, provider SDKs, domain logic.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @bstockwelldev/prompt-guardrails-core
15
+ ```
16
+
17
+ **For Vercel/CI:** Use the npm package (`^1.0.0`). For local development before first publish, consumers may use `file:../prompt-guardrails-core`; after publishing, switch to `^1.0.0`.
18
+
19
+ ## Public API
20
+
21
+ - `createPromptRuntime(config)` – Create guarded prompt runtime
22
+ - `withPromptGuardrails(config, handler)` – Wrap route handlers / server actions
23
+ - `buildStructuredPrompt({ system, userData, context })` – Instruction/data separation
24
+ - `validatePromptInput(input, policy)` – Input guardrails
25
+ - `validatePromptOutput(output, schema, policy)` – Output validation
26
+ - `repairJsonOutput(raw, schemaName)` – JSON repair orchestration
27
+ - `createTelemetryEvent(event)` – Privacy-safe telemetry
28
+ - `PromptGuardrailsError` – Machine-readable refusal reasons
29
+
30
+ ## Usage
31
+
32
+ ```ts
33
+ import {
34
+ createPromptRuntime,
35
+ parsePolicyRef,
36
+ type PromptPolicy,
37
+ } from '@bstockwelldev/prompt-guardrails-core';
38
+
39
+ const getPolicy: (id: string, version: string) => PromptPolicy | null = (id, version) => {
40
+ if (id === 'support_chatbot' && version === '1.3.0') {
41
+ return {
42
+ id,
43
+ version,
44
+ key: `${id}@${version}`,
45
+ system: 'You are a courteous support agent.',
46
+ constraints: { maxTokens: 800, allowUrls: false },
47
+ };
48
+ }
49
+ return null;
50
+ };
51
+
52
+ const runtime = createPromptRuntime({
53
+ getPolicy,
54
+ invokeGateway: async ({ messages, policy }) => {
55
+ // Host app performs actual LLM call
56
+ return await yourGateway.generateText(messages);
57
+ },
58
+ });
59
+
60
+ const result = await runtime.invoke('support_chatbot@1.3.0', userInput, {
61
+ requestId: 'req-123',
62
+ tenantId: 'tenant-1',
63
+ });
64
+ ```
65
+
66
+ ## Refusal Reasons
67
+
68
+ - `injection_detected` – Prompt injection pattern detected
69
+ - `url_blocked` – URLs not allowed by policy
70
+ - `policy_disabled` – Prompt disabled or unknown
71
+ - `schema_invalid` – Output failed schema validation
72
+ - `output_leakage_detected` – Output contains disallowed content
73
+ - `input_too_long` – Input exceeds max length
74
+ - `control_characters_blocked` – Disallowed control chars in input
75
+
76
+ ## Repository
77
+
78
+ - **Source**: https://github.com/bstockwelldev/prompt-guardrails-core
79
+ - **npm**: https://www.npmjs.com/package/@bstockwelldev/prompt-guardrails-core
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Machine-readable refusal reasons for prompt guardrails.
3
+ * Used by host apps for logging, metrics, and user-facing messaging.
4
+ */
5
+ export type PromptRefusalReason = 'injection_detected' | 'url_blocked' | 'policy_disabled' | 'schema_invalid' | 'output_leakage_detected' | 'input_too_long' | 'control_characters_blocked';
6
+ export declare class PromptGuardrailsError extends Error {
7
+ readonly reason: PromptRefusalReason;
8
+ readonly details?: string;
9
+ constructor(reason: PromptRefusalReason, message: string, details?: string);
10
+ }
11
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAC3B,oBAAoB,GACpB,aAAa,GACb,iBAAiB,GACjB,gBAAgB,GAChB,yBAAyB,GACzB,gBAAgB,GAChB,4BAA4B,CAAC;AAEjC,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;gBAEd,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAO3E"}
package/dist/errors.js ADDED
@@ -0,0 +1,10 @@
1
+ export class PromptGuardrailsError extends Error {
2
+ constructor(reason, message, details) {
3
+ super(message);
4
+ this.name = 'PromptGuardrailsError';
5
+ this.reason = reason;
6
+ this.details = details;
7
+ Object.setPrototypeOf(this, PromptGuardrailsError.prototype);
8
+ }
9
+ }
10
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAI9C,YAAY,MAA2B,EAAE,OAAe,EAAE,OAAgB;QACxE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC/D,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @bstockwelldev/prompt-guardrails-core
3
+ *
4
+ * Stateless server-side prompt guardrails: policy, input/output validation,
5
+ * structured invocation, and privacy-safe telemetry.
6
+ *
7
+ * The module owns prompt policy and enforcement.
8
+ * The host app owns provider selection, API keys, routing, auth, and domain orchestration.
9
+ */
10
+ export { PromptGuardrailsError, type PromptRefusalReason, } from './errors.js';
11
+ export type { PromptPolicy, PolicyRef, PromptInvocation, PromptInvocationResult, PromptTelemetryEvent, OutputSchema, } from './types.js';
12
+ export { validatePromptInput, normalizeWhitespace, stripInvisibleChars, containsUrl, checkInjectionPatterns, scrubSensitiveText, } from './input.js';
13
+ export { validatePromptOutput, repairJsonOutput, parseStructuredOutput, repairMalformedJson, checkLeakagePatterns, } from './output.js';
14
+ export { buildStructuredPrompt, buildMessages, type StructuredPromptInput, } from './prompt.js';
15
+ export { createTelemetryEvent, } from './telemetry.js';
16
+ export { parsePolicyRef, loadPolicyConfig, checkPolicyEnabled, createPromptPolicyRegistry, type PolicyRegistry, type PromptRuntimeConfig, } from './policy.js';
17
+ export { createPromptRuntime, type GatewayAdapter, type CreatePromptRuntimeOptions, } from './runtime.js';
18
+ export { withPromptGuardrails, type InvocationHandler, type InvocationContext, } from './middleware.js';
19
+ export { PromptPolicyEntrySchema, PromptRegistrySchema, PolicyConstraintsSchema, type PromptPolicyEntry, type PolicyConstraints, } from './schemas.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,qBAAqB,EACrB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,EACpB,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAC1B,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,0BAA0B,GAChC,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,oBAAoB,EACpB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @bstockwelldev/prompt-guardrails-core
3
+ *
4
+ * Stateless server-side prompt guardrails: policy, input/output validation,
5
+ * structured invocation, and privacy-safe telemetry.
6
+ *
7
+ * The module owns prompt policy and enforcement.
8
+ * The host app owns provider selection, API keys, routing, auth, and domain orchestration.
9
+ */
10
+ export { PromptGuardrailsError, } from './errors.js';
11
+ export { validatePromptInput, normalizeWhitespace, stripInvisibleChars, containsUrl, checkInjectionPatterns, scrubSensitiveText, } from './input.js';
12
+ export { validatePromptOutput, repairJsonOutput, parseStructuredOutput, repairMalformedJson, checkLeakagePatterns, } from './output.js';
13
+ export { buildStructuredPrompt, buildMessages, } from './prompt.js';
14
+ export { createTelemetryEvent, } from './telemetry.js';
15
+ export { parsePolicyRef, loadPolicyConfig, checkPolicyEnabled, createPromptPolicyRegistry, } from './policy.js';
16
+ export { createPromptRuntime, } from './runtime.js';
17
+ export { withPromptGuardrails, } from './middleware.js';
18
+ export { PromptPolicyEntrySchema, PromptRegistrySchema, PolicyConstraintsSchema, } from './schemas.js';
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,qBAAqB,GAEtB,MAAM,aAAa,CAAC;AAWrB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,qBAAqB,EACrB,aAAa,GAEd,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,GAG3B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,GAGpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,oBAAoB,GAGrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,GAGxB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { PromptPolicy } from './types.js';
2
+ /**
3
+ * Z3: Normalize whitespace (collapse runs, trim).
4
+ */
5
+ export declare function normalizeWhitespace(text: string): string;
6
+ /**
7
+ * Z3: Strip invisible/control characters.
8
+ */
9
+ export declare function stripInvisibleChars(text: string): string;
10
+ /**
11
+ * Z3: Check if text contains URLs.
12
+ */
13
+ export declare function containsUrl(text: string): boolean;
14
+ /**
15
+ * Z3: Check for prompt injection patterns.
16
+ */
17
+ export declare function checkInjectionPatterns(text: string): string | null;
18
+ /**
19
+ * Z3: Scrub sensitive text for telemetry (redact PII, secrets).
20
+ */
21
+ export declare function scrubSensitiveText(text: string): string;
22
+ /**
23
+ * Z2: Validate prompt input against policy.
24
+ * Throws PromptGuardrailsError on policy violation.
25
+ */
26
+ export declare function validatePromptInput(input: string, policy: PromptPolicy): string;
27
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAc/C;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMlE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAevD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAuC/E"}
package/dist/input.js ADDED
@@ -0,0 +1,85 @@
1
+ import { PromptGuardrailsError } from './errors.js';
2
+ const INJECTION_PATTERNS = [
3
+ { pattern: /(\bsystem|\bassistant|\bdeveloper|\btool)\s*:/i, reason: 'injection_detected' },
4
+ { pattern: /ignore\s+all\s+previous\s+instructions/i, reason: 'injection_detected' },
5
+ { pattern: /simulate\s+being\s+a\s+different\s+model/i, reason: 'injection_detected' },
6
+ ];
7
+ const URL_PATTERN = /(https?:\/\/|www\.)/i;
8
+ /** Control chars and zero-width chars that can obfuscate injection */
9
+ const CONTROL_CHARS = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\u200B-\u200D\uFEFF]/g;
10
+ /**
11
+ * Z3: Normalize whitespace (collapse runs, trim).
12
+ */
13
+ export function normalizeWhitespace(text) {
14
+ return text.replace(/\s+/g, ' ').trim();
15
+ }
16
+ /**
17
+ * Z3: Strip invisible/control characters.
18
+ */
19
+ export function stripInvisibleChars(text) {
20
+ return text.replace(CONTROL_CHARS, '');
21
+ }
22
+ /**
23
+ * Z3: Check if text contains URLs.
24
+ */
25
+ export function containsUrl(text) {
26
+ return URL_PATTERN.test(text);
27
+ }
28
+ /**
29
+ * Z3: Check for prompt injection patterns.
30
+ */
31
+ export function checkInjectionPatterns(text) {
32
+ const lower = text.toLowerCase();
33
+ for (const { pattern, reason } of INJECTION_PATTERNS) {
34
+ if (pattern.test(lower))
35
+ return reason;
36
+ }
37
+ return null;
38
+ }
39
+ /**
40
+ * Z3: Scrub sensitive text for telemetry (redact PII, secrets).
41
+ */
42
+ export function scrubSensitiveText(text) {
43
+ let out = text;
44
+ const secrets = [
45
+ { rx: /api[_-]?key[:\s]+(\S+)/gi, rep: 'apiKey: [REDACTED]' },
46
+ { rx: /authorization[:\s]+(Bearer\s+\S+)/gi, rep: 'authorization: [REDACTED]' },
47
+ { rx: /token[:\s]+(\S+)/gi, rep: 'token: [REDACTED]' },
48
+ ];
49
+ const pii = [
50
+ /\b\d{3}-\d{2}-\d{4}\b/g,
51
+ /\b\d{12,19}\b/g,
52
+ /\b[\w.+-]+@[\w.-]+\.[a-zA-Z]{2,}\b/g,
53
+ ];
54
+ for (const { rx, rep } of secrets)
55
+ out = out.replace(rx, rep);
56
+ for (const rx of pii)
57
+ out = out.replace(rx, '[REDACTED]');
58
+ return out.slice(0, 8000);
59
+ }
60
+ /**
61
+ * Z2: Validate prompt input against policy.
62
+ * Throws PromptGuardrailsError on policy violation.
63
+ */
64
+ export function validatePromptInput(input, policy) {
65
+ let normalized = input;
66
+ normalized = stripInvisibleChars(normalized);
67
+ normalized = normalizeWhitespace(normalized);
68
+ const maxLen = policy.constraints.maxInputLength ?? 64 * 1024;
69
+ if (normalized.length > maxLen) {
70
+ throw new PromptGuardrailsError('input_too_long', `Input exceeds max length (${maxLen})`, `length=${normalized.length}`);
71
+ }
72
+ const controlCheck = input.replace(CONTROL_CHARS, '');
73
+ if (controlCheck.length !== input.length) {
74
+ throw new PromptGuardrailsError('control_characters_blocked', 'Input contains disallowed control characters');
75
+ }
76
+ const injectionReason = checkInjectionPatterns(normalized);
77
+ if (injectionReason) {
78
+ throw new PromptGuardrailsError('injection_detected', 'Prompt injection pattern detected', injectionReason);
79
+ }
80
+ if (!policy.constraints.allowUrls && containsUrl(normalized)) {
81
+ throw new PromptGuardrailsError('url_blocked', 'URLs not allowed by policy');
82
+ }
83
+ return normalized;
84
+ }
85
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { PromptRuntimeConfig } from './policy.js';
2
+ import type { PromptInvocationResult } from './types.js';
3
+ export type InvocationContext = {
4
+ requestId: string;
5
+ tenantId?: string;
6
+ userId?: string;
7
+ };
8
+ export type InvocationHandler<TInput, TOutput, TData = unknown> = (input: TInput, context: InvocationContext, result: PromptInvocationResult<TData>) => Promise<TOutput>;
9
+ /**
10
+ * Wrap an invocation handler with prompt guardrails.
11
+ * Host apps use this for route handlers and server actions.
12
+ * The guardrails run the full flow (validate input, invoke gateway, validate output);
13
+ * the handler receives the result and returns the response.
14
+ */
15
+ export declare function withPromptGuardrails<TInput, TOutput, TData = unknown>(config: PromptRuntimeConfig & {
16
+ invokeGateway: import('./runtime.js').GatewayAdapter;
17
+ /** Extract policyRef from input */
18
+ getPolicyRef: (input: TInput) => string;
19
+ /** Extract user data from input */
20
+ getUserData: (input: TInput) => string;
21
+ /** Optional: extract context from input */
22
+ getContext?: (input: TInput) => {
23
+ tenantId?: string;
24
+ userId?: string;
25
+ };
26
+ /** Optional: output schema for structured validation */
27
+ outputSchema?: import('./types.js').OutputSchema<TData>;
28
+ }, handler: InvocationHandler<TInput, TOutput, TData>): (input: TInput, context: InvocationContext) => Promise<TOutput>;
29
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,OAAO,IAAI,CAChE,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,sBAAsB,CAAC,KAAK,CAAC,KAClC,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,OAAO,EACnE,MAAM,EAAE,mBAAmB,GAAG;IAC5B,aAAa,EAAE,OAAO,cAAc,EAAE,cAAc,CAAC;IACrD,mCAAmC;IACnC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,mCAAmC;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE,wDAAwD;IACxD,YAAY,CAAC,EAAE,OAAO,YAAY,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;CACzD,EACD,OAAO,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,GACjD,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,CA0BjE"}
@@ -0,0 +1,31 @@
1
+ import { createPromptRuntime } from './runtime.js';
2
+ /**
3
+ * Wrap an invocation handler with prompt guardrails.
4
+ * Host apps use this for route handlers and server actions.
5
+ * The guardrails run the full flow (validate input, invoke gateway, validate output);
6
+ * the handler receives the result and returns the response.
7
+ */
8
+ export function withPromptGuardrails(config, handler) {
9
+ const runtime = createPromptRuntime({
10
+ getPolicy: config.getPolicy,
11
+ isPromptEnabled: config.isPromptEnabled,
12
+ onTelemetry: config.onTelemetry,
13
+ invokeGateway: config.invokeGateway,
14
+ });
15
+ return async (input, ctx) => {
16
+ const policyRef = config.getPolicyRef(input);
17
+ const userData = config.getUserData(input);
18
+ const context = config.getContext?.(input) ?? {};
19
+ const result = await runtime.invoke(policyRef, userData, {
20
+ requestId: ctx.requestId,
21
+ tenantId: context.tenantId ?? ctx.tenantId,
22
+ userId: context.userId ?? ctx.userId,
23
+ outputSchema: config.outputSchema,
24
+ });
25
+ if (!result.success && result.refused) {
26
+ throw new Error(`Prompt guardrails refused: ${result.reason}`);
27
+ }
28
+ return handler(input, ctx, result);
29
+ };
30
+ }
31
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAcnD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAUC,EACD,OAAkD;IAElD,MAAM,OAAO,GAAG,mBAAmB,CAAC;QAClC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC,CAAC;IAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC1B,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAEjD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAQ,SAAS,EAAE,QAAQ,EAAE;YAC9D,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;YAC1C,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM;YACpC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,OAAO,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { OutputSchema } from './types.js';
2
+ /**
3
+ * Z3: Parse JSON from text, stripping markdown fences.
4
+ */
5
+ export declare function parseStructuredOutput<T>(text: string): T | null;
6
+ /**
7
+ * Z2: Repair malformed JSON from LLM output.
8
+ */
9
+ export declare function repairMalformedJson<T>(raw: string): T | null;
10
+ /**
11
+ * Z3: Check output for leakage patterns (secrets, PII).
12
+ */
13
+ export declare function checkLeakagePatterns(text: string): string | null;
14
+ /**
15
+ * Z2: Validate prompt output against schema and policy.
16
+ */
17
+ export declare function validatePromptOutput<T>(raw: string, schema: OutputSchema<T>): {
18
+ ok: true;
19
+ data: T;
20
+ } | {
21
+ ok: false;
22
+ reason: 'schema_invalid' | 'output_leakage_detected';
23
+ };
24
+ /**
25
+ * Z2: Repair JSON output with optional schema validation.
26
+ */
27
+ export declare function repairJsonOutput<T>(raw: string, schema: OutputSchema<T>): T | null;
28
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO/C;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAiB/D;AAmBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAsB5D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKhE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,GAAG,yBAAyB,CAAA;CAAE,CAmB7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,CAAC,GAAG,IAAI,CAOV"}
package/dist/output.js ADDED
@@ -0,0 +1,111 @@
1
+ const FENCE_REGEX = /^```(?:json)?\s*\n?(.*?)\n?\s*```$/s;
2
+ const TRAILING_COMMA_REGEX = /,\s*([}\]])/g;
3
+ const DISALLOWED_OUTPUT = [/password/i, /private key/i, /how to hack/i];
4
+ /**
5
+ * Z3: Parse JSON from text, stripping markdown fences.
6
+ */
7
+ export function parseStructuredOutput(text) {
8
+ let jsonStr = text.trim();
9
+ const match = jsonStr.match(FENCE_REGEX);
10
+ if (match?.[1])
11
+ jsonStr = match[1].trim();
12
+ else if (jsonStr.startsWith('```')) {
13
+ const first = jsonStr.indexOf('\n');
14
+ if (first !== -1) {
15
+ jsonStr = jsonStr.slice(first + 1).trim();
16
+ if (jsonStr.endsWith('```'))
17
+ jsonStr = jsonStr.slice(0, -3).trim();
18
+ }
19
+ }
20
+ try {
21
+ return JSON.parse(jsonStr);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ /**
28
+ * Z3: Fix trailing commas in JSON string.
29
+ */
30
+ function fixTrailingCommas(jsonStr) {
31
+ return jsonStr.replace(TRAILING_COMMA_REGEX, '$1');
32
+ }
33
+ /**
34
+ * Z3: Extract JSON object between first { and last }.
35
+ */
36
+ function extractJsonObject(text) {
37
+ const first = text.indexOf('{');
38
+ const last = text.lastIndexOf('}');
39
+ if (first === -1 || last <= first)
40
+ return null;
41
+ return text.slice(first, last + 1);
42
+ }
43
+ /**
44
+ * Z2: Repair malformed JSON from LLM output.
45
+ */
46
+ export function repairMalformedJson(raw) {
47
+ let jsonStr = raw.trim();
48
+ const match = jsonStr.match(FENCE_REGEX);
49
+ if (match?.[1])
50
+ jsonStr = match[1].trim();
51
+ const attempts = [
52
+ () => JSON.parse(jsonStr),
53
+ () => JSON.parse(fixTrailingCommas(jsonStr)),
54
+ () => {
55
+ const extracted = extractJsonObject(jsonStr);
56
+ return extracted ? JSON.parse(extracted) : null;
57
+ },
58
+ ];
59
+ for (const attempt of attempts) {
60
+ try {
61
+ return attempt();
62
+ }
63
+ catch {
64
+ continue;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ /**
70
+ * Z3: Check output for leakage patterns (secrets, PII).
71
+ */
72
+ export function checkLeakagePatterns(text) {
73
+ for (const rx of DISALLOWED_OUTPUT) {
74
+ if (rx.test(text))
75
+ return 'output_leakage_detected';
76
+ }
77
+ return null;
78
+ }
79
+ /**
80
+ * Z2: Validate prompt output against schema and policy.
81
+ */
82
+ export function validatePromptOutput(raw, schema) {
83
+ const leakage = checkLeakagePatterns(raw);
84
+ if (leakage) {
85
+ return { ok: false, reason: 'output_leakage_detected' };
86
+ }
87
+ let parsed = parseStructuredOutput(raw);
88
+ if (parsed === null)
89
+ parsed = repairMalformedJson(raw);
90
+ if (parsed === null) {
91
+ return { ok: false, reason: 'schema_invalid' };
92
+ }
93
+ const result = schema.safeParse(parsed);
94
+ if (!result.success) {
95
+ return { ok: false, reason: 'schema_invalid' };
96
+ }
97
+ return { ok: true, data: result.data };
98
+ }
99
+ /**
100
+ * Z2: Repair JSON output with optional schema validation.
101
+ */
102
+ export function repairJsonOutput(raw, schema) {
103
+ let parsed = parseStructuredOutput(raw);
104
+ if (parsed === null)
105
+ parsed = repairMalformedJson(raw);
106
+ if (parsed === null)
107
+ return null;
108
+ const result = schema.safeParse(parsed);
109
+ return result.success ? result.data : null;
110
+ }
111
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { PromptPolicy, PolicyRef } from './types.js';
2
+ /**
3
+ * Z3: Parse policy reference "id@version" or "id@v1.2.3".
4
+ */
5
+ export declare function parsePolicyRef(policy: string): PolicyRef;
6
+ export type PolicyRegistry = (id: string, version: string) => PromptPolicy | null;
7
+ export type PromptRuntimeConfig = {
8
+ /** Resolve policy by id and version */
9
+ getPolicy: PolicyRegistry;
10
+ /** Optional: check if prompt is enabled (feature flag) */
11
+ isPromptEnabled?: (id: string, version: string) => boolean;
12
+ /** Optional: emit telemetry events */
13
+ onTelemetry?: (event: import('./types.js').PromptTelemetryEvent) => void;
14
+ };
15
+ /**
16
+ * Z2: Load policy config from registry.
17
+ */
18
+ export declare function loadPolicyConfig(policyRef: string, getPolicy: PolicyRegistry): PromptPolicy;
19
+ /**
20
+ * Z2: Check if policy is enabled (when feature flag provided).
21
+ */
22
+ export declare function checkPolicyEnabled(policy: PromptPolicy, isEnabled?: (id: string, version: string) => boolean): boolean;
23
+ /**
24
+ * Create a PolicyRegistry from registry JSON.
25
+ * Host apps can load and validate their registry, then pass the result.
26
+ */
27
+ export declare function createPromptPolicyRegistry(registry: unknown): PolicyRegistry;
28
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG1D;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CASxD;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC;AAElF,MAAM,MAAM,mBAAmB,GAAG;IAChC,uCAAuC;IACvC,SAAS,EAAE,cAAc,CAAC;IAC1B,0DAA0D;IAC1D,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3D,sCAAsC;IACtC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAC;CAC1E,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,cAAc,GACxB,YAAY,CAOd;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,GACnD,OAAO,CAGT;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,OAAO,GAChB,cAAc,CAmBhB"}
package/dist/policy.js ADDED
@@ -0,0 +1,60 @@
1
+ import { PromptRegistrySchema } from './schemas.js';
2
+ /**
3
+ * Z3: Parse policy reference "id@version" or "id@v1.2.3".
4
+ */
5
+ export function parsePolicyRef(policy) {
6
+ const atIndex = policy.indexOf('@');
7
+ if (atIndex === -1) {
8
+ throw new Error(`Invalid policy reference: ${policy}`);
9
+ }
10
+ const idPart = policy.slice(0, atIndex);
11
+ let versionPart = policy.slice(atIndex + 1);
12
+ if (versionPart.startsWith('v'))
13
+ versionPart = versionPart.slice(1);
14
+ return { id: idPart, version: versionPart, key: policy };
15
+ }
16
+ /**
17
+ * Z2: Load policy config from registry.
18
+ */
19
+ export function loadPolicyConfig(policyRef, getPolicy) {
20
+ const ref = parsePolicyRef(policyRef);
21
+ const policy = getPolicy(ref.id, ref.version);
22
+ if (!policy) {
23
+ throw new Error(`Unknown policy ${policyRef}`);
24
+ }
25
+ return policy;
26
+ }
27
+ /**
28
+ * Z2: Check if policy is enabled (when feature flag provided).
29
+ */
30
+ export function checkPolicyEnabled(policy, isEnabled) {
31
+ if (!isEnabled)
32
+ return true;
33
+ return isEnabled(policy.id, policy.version);
34
+ }
35
+ /**
36
+ * Create a PolicyRegistry from registry JSON.
37
+ * Host apps can load and validate their registry, then pass the result.
38
+ */
39
+ export function createPromptPolicyRegistry(registry) {
40
+ const entries = PromptRegistrySchema.parse(registry);
41
+ return (id, version) => {
42
+ const entry = entries.find((e) => e.id === id && e.version === version);
43
+ if (!entry)
44
+ return null;
45
+ return {
46
+ id: entry.id,
47
+ version: entry.version,
48
+ key: `${entry.id}@${entry.version}`,
49
+ system: entry.system,
50
+ constraints: {
51
+ maxTokens: entry.constraints.maxTokens,
52
+ temperature: entry.constraints.temperature,
53
+ allowUrls: entry.constraints.allowUrls ?? false,
54
+ maxInputLength: entry.constraints.maxInputLength,
55
+ tools: entry.constraints.tools,
56
+ },
57
+ };
58
+ };
59
+ }
60
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACxC,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IAC5C,IAAI,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAC3D,CAAC;AAaD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,SAAiB,EACjB,SAAyB;IAEzB,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,SAAS,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAoB,EACpB,SAAoD;IAEpD,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACxC,QAAiB;IAEjB,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrD,OAAO,CAAC,EAAU,EAAE,OAAe,EAAuB,EAAE;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;QACxE,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,OAAO;YACL,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE;YACnC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,WAAW,EAAE;gBACX,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,SAAS;gBACtC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,WAAW;gBAC1C,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,SAAS,IAAI,KAAK;gBAC/C,cAAc,EAAE,KAAK,CAAC,WAAW,CAAC,cAAc;gBAChD,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,KAAK;aAC/B;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Build a structured prompt with clear separation of system instructions
3
+ * from user data. Uses XML-style delimiters for robustness.
4
+ */
5
+ export type StructuredPromptInput = {
6
+ system: string;
7
+ userData: string;
8
+ context?: string;
9
+ };
10
+ /**
11
+ * Build a structured prompt with instruction/data separation.
12
+ * System instructions remain separate; user data is wrapped in delimiters.
13
+ */
14
+ export declare function buildStructuredPrompt(input: StructuredPromptInput): string;
15
+ /**
16
+ * Build messages array for SDK consumers (system + user).
17
+ */
18
+ export declare function buildMessages(input: StructuredPromptInput): Array<{
19
+ role: 'user' | 'system';
20
+ content: string;
21
+ }>;
22
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAOF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAU1E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,qBAAqB,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAU/G"}
package/dist/prompt.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Build a structured prompt with clear separation of system instructions
3
+ * from user data. Uses XML-style delimiters for robustness.
4
+ */
5
+ const USER_DATA_START = '<user_data>';
6
+ const USER_DATA_END = '</user_data>';
7
+ const CONTEXT_START = '<context>';
8
+ const CONTEXT_END = '</context>';
9
+ /**
10
+ * Build a structured prompt with instruction/data separation.
11
+ * System instructions remain separate; user data is wrapped in delimiters.
12
+ */
13
+ export function buildStructuredPrompt(input) {
14
+ const parts = [input.system];
15
+ if (input.context?.trim()) {
16
+ parts.push(`${CONTEXT_START}\n${input.context.trim()}\n${CONTEXT_END}`);
17
+ }
18
+ parts.push(`${USER_DATA_START}\n${input.userData.trim()}\n${USER_DATA_END}`);
19
+ return parts.join('\n\n');
20
+ }
21
+ /**
22
+ * Build messages array for SDK consumers (system + user).
23
+ */
24
+ export function buildMessages(input) {
25
+ const systemParts = [input.system];
26
+ if (input.context?.trim()) {
27
+ systemParts.push(`${CONTEXT_START}\n${input.context.trim()}\n${CONTEXT_END}`);
28
+ }
29
+ return [
30
+ { role: 'system', content: systemParts.join('\n\n') },
31
+ { role: 'user', content: input.userData.trim() },
32
+ ];
33
+ }
34
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,eAAe,GAAG,aAAa,CAAC;AACtC,MAAM,aAAa,GAAG,cAAc,CAAC;AACrC,MAAM,aAAa,GAAG,WAAW,CAAC;AAClC,MAAM,WAAW,GAAG,YAAY,CAAC;AAEjC;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAA4B;IAChE,MAAM,KAAK,GAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAEvC,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,aAAa,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,WAAW,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,KAAK,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,aAAa,EAAE,CAAC,CAAC;IAE7E,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAA4B;IACxD,MAAM,WAAW,GAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,WAAW,CAAC,IAAI,CAAC,GAAG,aAAa,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,WAAW,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,OAAO;QACL,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;QACrD,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE;KACjD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { PromptPolicy, PromptInvocationResult } from './types.js';
2
+ import type { OutputSchema } from './types.js';
3
+ import { type PromptRuntimeConfig } from './policy.js';
4
+ export type GatewayAdapter = (params: {
5
+ messages: Array<{
6
+ role: 'user' | 'system';
7
+ content: string;
8
+ }>;
9
+ policy: PromptPolicy;
10
+ requestId: string;
11
+ }) => Promise<string>;
12
+ export type CreatePromptRuntimeOptions = PromptRuntimeConfig & {
13
+ /** Host-provided gateway that performs the actual LLM call */
14
+ invokeGateway: GatewayAdapter;
15
+ };
16
+ /**
17
+ * Z1: Create a guarded prompt runtime.
18
+ * Orchestrates: load policy → validate input → invoke gateway → validate output → emit telemetry.
19
+ */
20
+ export declare function createPromptRuntime(config: CreatePromptRuntimeOptions): {
21
+ invoke<T>(policyRef: string, userData: string, options?: {
22
+ systemContext?: string;
23
+ outputSchema?: OutputSchema<T>;
24
+ requestId?: string;
25
+ tenantId?: string;
26
+ userId?: string;
27
+ }): Promise<PromptInvocationResult<T>>;
28
+ };
29
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAwB,MAAM,YAAY,CAAC;AAC7F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAwC,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAM7F,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE;IACpC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEtB,MAAM,MAAM,0BAA0B,GAAG,mBAAmB,GAAG;IAC7D,8DAA8D;IAC9D,aAAa,EAAE,cAAc,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,0BAA0B;WAIrD,CAAC,aACD,MAAM,YACP,MAAM,YACN;QACR,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;EAwIxC"}
@@ -0,0 +1,144 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { PromptGuardrailsError } from './errors.js';
3
+ import { loadPolicyConfig, checkPolicyEnabled } from './policy.js';
4
+ import { validatePromptInput } from './input.js';
5
+ import { validatePromptOutput } from './output.js';
6
+ import { buildMessages } from './prompt.js';
7
+ import { createTelemetryEvent } from './telemetry.js';
8
+ /**
9
+ * Z1: Create a guarded prompt runtime.
10
+ * Orchestrates: load policy → validate input → invoke gateway → validate output → emit telemetry.
11
+ */
12
+ export function createPromptRuntime(config) {
13
+ const { getPolicy, isPromptEnabled, onTelemetry, invokeGateway } = config;
14
+ return {
15
+ async invoke(policyRef, userData, options) {
16
+ const requestId = options?.requestId ?? randomUUID();
17
+ let policy;
18
+ try {
19
+ policy = loadPolicyConfig(policyRef, getPolicy);
20
+ }
21
+ catch (err) {
22
+ return {
23
+ success: false,
24
+ refused: true,
25
+ reason: 'policy_disabled',
26
+ requestId,
27
+ message: err instanceof Error ? err.message : String(err),
28
+ };
29
+ }
30
+ if (!checkPolicyEnabled(policy, isPromptEnabled)) {
31
+ return {
32
+ success: false,
33
+ refused: true,
34
+ reason: 'policy_disabled',
35
+ requestId,
36
+ };
37
+ }
38
+ let validatedInput;
39
+ try {
40
+ validatedInput = validatePromptInput(userData, policy);
41
+ }
42
+ catch (err) {
43
+ if (err instanceof PromptGuardrailsError) {
44
+ onTelemetry?.(createTelemetryEvent({
45
+ requestId,
46
+ policyRef,
47
+ promptId: policy.id,
48
+ promptVersion: policy.version,
49
+ promptText: userData,
50
+ outputText: '',
51
+ latencyMs: 0,
52
+ tenantId: options?.tenantId,
53
+ userId: options?.userId,
54
+ policyHit: err.reason,
55
+ }));
56
+ return {
57
+ success: false,
58
+ refused: true,
59
+ reason: err.reason,
60
+ requestId,
61
+ message: err.message,
62
+ };
63
+ }
64
+ throw err;
65
+ }
66
+ const messages = buildMessages({
67
+ system: policy.system,
68
+ userData: validatedInput,
69
+ context: options?.systemContext,
70
+ });
71
+ const start = Date.now();
72
+ let rawOutput;
73
+ try {
74
+ rawOutput = await invokeGateway({
75
+ messages,
76
+ policy,
77
+ requestId,
78
+ });
79
+ }
80
+ catch (err) {
81
+ throw err;
82
+ }
83
+ const latencyMs = Date.now() - start;
84
+ if (options?.outputSchema) {
85
+ const validated = validatePromptOutput(rawOutput, options.outputSchema);
86
+ if (!validated.ok) {
87
+ onTelemetry?.(createTelemetryEvent({
88
+ requestId,
89
+ policyRef,
90
+ promptId: policy.id,
91
+ promptVersion: policy.version,
92
+ promptText: validatedInput,
93
+ outputText: rawOutput,
94
+ latencyMs,
95
+ tenantId: options?.tenantId,
96
+ userId: options?.userId,
97
+ policyHit: validated.reason,
98
+ }));
99
+ return {
100
+ success: false,
101
+ refused: true,
102
+ reason: validated.reason,
103
+ requestId,
104
+ };
105
+ }
106
+ onTelemetry?.(createTelemetryEvent({
107
+ requestId,
108
+ policyRef,
109
+ promptId: policy.id,
110
+ promptVersion: policy.version,
111
+ promptText: validatedInput,
112
+ outputText: rawOutput,
113
+ latencyMs,
114
+ tenantId: options?.tenantId,
115
+ userId: options?.userId,
116
+ }));
117
+ return {
118
+ success: true,
119
+ data: validated.data,
120
+ requestId,
121
+ refused: false,
122
+ };
123
+ }
124
+ onTelemetry?.(createTelemetryEvent({
125
+ requestId,
126
+ policyRef,
127
+ promptId: policy.id,
128
+ promptVersion: policy.version,
129
+ promptText: validatedInput,
130
+ outputText: rawOutput,
131
+ latencyMs,
132
+ tenantId: options?.tenantId,
133
+ userId: options?.userId,
134
+ }));
135
+ return {
136
+ success: true,
137
+ data: rawOutput,
138
+ requestId,
139
+ refused: false,
140
+ };
141
+ },
142
+ };
143
+ }
144
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Zod schema for prompt policy constraints.
4
+ */
5
+ export declare const PolicyConstraintsSchema: z.ZodObject<{
6
+ maxTokens: z.ZodNumber;
7
+ temperature: z.ZodOptional<z.ZodNumber>;
8
+ allowUrls: z.ZodDefault<z.ZodBoolean>;
9
+ maxInputLength: z.ZodOptional<z.ZodNumber>;
10
+ tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ maxTokens: number;
13
+ allowUrls: boolean;
14
+ temperature?: number | undefined;
15
+ maxInputLength?: number | undefined;
16
+ tools?: string[] | undefined;
17
+ }, {
18
+ maxTokens: number;
19
+ temperature?: number | undefined;
20
+ allowUrls?: boolean | undefined;
21
+ maxInputLength?: number | undefined;
22
+ tools?: string[] | undefined;
23
+ }>;
24
+ /**
25
+ * Zod schema for a single prompt policy entry.
26
+ */
27
+ export declare const PromptPolicyEntrySchema: z.ZodObject<{
28
+ id: z.ZodString;
29
+ version: z.ZodString;
30
+ system: z.ZodString;
31
+ constraints: z.ZodObject<{
32
+ maxTokens: z.ZodNumber;
33
+ temperature: z.ZodOptional<z.ZodNumber>;
34
+ allowUrls: z.ZodDefault<z.ZodBoolean>;
35
+ maxInputLength: z.ZodOptional<z.ZodNumber>;
36
+ tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
37
+ }, "strip", z.ZodTypeAny, {
38
+ maxTokens: number;
39
+ allowUrls: boolean;
40
+ temperature?: number | undefined;
41
+ maxInputLength?: number | undefined;
42
+ tools?: string[] | undefined;
43
+ }, {
44
+ maxTokens: number;
45
+ temperature?: number | undefined;
46
+ allowUrls?: boolean | undefined;
47
+ maxInputLength?: number | undefined;
48
+ tools?: string[] | undefined;
49
+ }>;
50
+ }, "strip", z.ZodTypeAny, {
51
+ system: string;
52
+ id: string;
53
+ version: string;
54
+ constraints: {
55
+ maxTokens: number;
56
+ allowUrls: boolean;
57
+ temperature?: number | undefined;
58
+ maxInputLength?: number | undefined;
59
+ tools?: string[] | undefined;
60
+ };
61
+ }, {
62
+ system: string;
63
+ id: string;
64
+ version: string;
65
+ constraints: {
66
+ maxTokens: number;
67
+ temperature?: number | undefined;
68
+ allowUrls?: boolean | undefined;
69
+ maxInputLength?: number | undefined;
70
+ tools?: string[] | undefined;
71
+ };
72
+ }>;
73
+ /**
74
+ * Zod schema for a prompt policy registry (array of entries).
75
+ */
76
+ export declare const PromptRegistrySchema: z.ZodArray<z.ZodObject<{
77
+ id: z.ZodString;
78
+ version: z.ZodString;
79
+ system: z.ZodString;
80
+ constraints: z.ZodObject<{
81
+ maxTokens: z.ZodNumber;
82
+ temperature: z.ZodOptional<z.ZodNumber>;
83
+ allowUrls: z.ZodDefault<z.ZodBoolean>;
84
+ maxInputLength: z.ZodOptional<z.ZodNumber>;
85
+ tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
86
+ }, "strip", z.ZodTypeAny, {
87
+ maxTokens: number;
88
+ allowUrls: boolean;
89
+ temperature?: number | undefined;
90
+ maxInputLength?: number | undefined;
91
+ tools?: string[] | undefined;
92
+ }, {
93
+ maxTokens: number;
94
+ temperature?: number | undefined;
95
+ allowUrls?: boolean | undefined;
96
+ maxInputLength?: number | undefined;
97
+ tools?: string[] | undefined;
98
+ }>;
99
+ }, "strip", z.ZodTypeAny, {
100
+ system: string;
101
+ id: string;
102
+ version: string;
103
+ constraints: {
104
+ maxTokens: number;
105
+ allowUrls: boolean;
106
+ temperature?: number | undefined;
107
+ maxInputLength?: number | undefined;
108
+ tools?: string[] | undefined;
109
+ };
110
+ }, {
111
+ system: string;
112
+ id: string;
113
+ version: string;
114
+ constraints: {
115
+ maxTokens: number;
116
+ temperature?: number | undefined;
117
+ allowUrls?: boolean | undefined;
118
+ maxInputLength?: number | undefined;
119
+ tools?: string[] | undefined;
120
+ };
121
+ }>, "many">;
122
+ export type PromptPolicyEntry = z.infer<typeof PromptPolicyEntrySchema>;
123
+ export type PolicyConstraints = z.infer<typeof PolicyConstraintsSchema>;
124
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;EAMlC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKlC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAA0C,CAAC;AAE5E,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Zod schema for prompt policy constraints.
4
+ */
5
+ export const PolicyConstraintsSchema = z.object({
6
+ maxTokens: z.number().int().positive(),
7
+ temperature: z.number().min(0).max(2).optional(),
8
+ allowUrls: z.boolean().default(false),
9
+ maxInputLength: z.number().int().positive().optional(),
10
+ tools: z.array(z.string()).optional(),
11
+ });
12
+ /**
13
+ * Zod schema for a single prompt policy entry.
14
+ */
15
+ export const PromptPolicyEntrySchema = z.object({
16
+ id: z.string().min(1),
17
+ version: z.string().regex(/^\d+\.\d+\.\d+$/, 'version must be semver (e.g. 1.2.3)'),
18
+ system: z.string().min(1),
19
+ constraints: PolicyConstraintsSchema,
20
+ });
21
+ /**
22
+ * Zod schema for a prompt policy registry (array of entries).
23
+ */
24
+ export const PromptRegistrySchema = z.array(PromptPolicyEntrySchema).min(1);
25
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACtC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACrC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACtD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACtC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,qCAAqC,CAAC;IACnF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,WAAW,EAAE,uBAAuB;CACrC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { PromptTelemetryEvent } from './types.js';
2
+ import type { PromptRefusalReason } from './errors.js';
3
+ /**
4
+ * Create a privacy-safe telemetry event.
5
+ * Default: hashed prompt/output only; no raw content.
6
+ */
7
+ export declare function createTelemetryEvent(params: {
8
+ requestId: string;
9
+ policyRef: string;
10
+ promptId: string;
11
+ promptVersion: string;
12
+ promptText: string;
13
+ outputText: string;
14
+ latencyMs: number;
15
+ tenantId?: string;
16
+ userId?: string;
17
+ policyHit?: PromptRefusalReason | null;
18
+ toolNames?: string[];
19
+ }): PromptTelemetryEvent;
20
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAevD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE;IACN,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GACA,oBAAoB,CAsBtB"}
@@ -0,0 +1,38 @@
1
+ import { scrubSensitiveText } from './input.js';
2
+ /**
3
+ * FNV-1a hash for content identification without revealing content.
4
+ */
5
+ function hash(text) {
6
+ let value = 0x811c9dc5;
7
+ for (let i = 0; i < text.length; i++) {
8
+ value ^= text.charCodeAt(i);
9
+ value = (value * 0x01000193) >>> 0;
10
+ }
11
+ return value.toString(36).padStart(10, '0').slice(-10);
12
+ }
13
+ /**
14
+ * Create a privacy-safe telemetry event.
15
+ * Default: hashed prompt/output only; no raw content.
16
+ */
17
+ export function createTelemetryEvent(params) {
18
+ const sanitizedPrompt = scrubSensitiveText(params.promptText);
19
+ const sanitizedOutput = scrubSensitiveText(params.outputText);
20
+ const tokensIn = Math.ceil(sanitizedPrompt.length / 4);
21
+ const tokensOut = Math.ceil(sanitizedOutput.length / 4);
22
+ return {
23
+ requestId: params.requestId,
24
+ policyRef: params.policyRef,
25
+ promptId: params.promptId,
26
+ promptVersion: params.promptVersion,
27
+ promptHash: hash(sanitizedPrompt),
28
+ outputHash: hash(sanitizedOutput),
29
+ latencyMs: params.latencyMs,
30
+ tokensIn,
31
+ tokensOut,
32
+ tenantId: params.tenantId,
33
+ userId: params.userId,
34
+ policyHit: params.policyHit ?? null,
35
+ toolNames: params.toolNames,
36
+ };
37
+ }
38
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD;;GAEG;AACH,SAAS,IAAI,CAAC,IAAY;IACxB,IAAI,KAAK,GAAG,UAAU,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC5B,KAAK,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAYC;IAED,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAE9D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAExD,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC;QACjC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC;QACjC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ;QACR,SAAS;QACT,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI;QACnC,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,82 @@
1
+ import type { ZodType } from 'zod';
2
+ import type { PromptRefusalReason } from './errors.js';
3
+ /**
4
+ * Versioned prompt policy contract.
5
+ * Host apps supply policy data; the shared module validates and enforces it.
6
+ */
7
+ export type PromptPolicy = {
8
+ id: string;
9
+ version: string;
10
+ key: string;
11
+ system: string;
12
+ constraints: {
13
+ maxTokens: number;
14
+ temperature?: number;
15
+ allowUrls?: boolean;
16
+ maxInputLength?: number;
17
+ tools?: string[];
18
+ };
19
+ };
20
+ /**
21
+ * Policy reference format: "promptId@version" (e.g. "support_chatbot@1.3.0")
22
+ */
23
+ export type PolicyRef = {
24
+ id: string;
25
+ version: string;
26
+ key: string;
27
+ };
28
+ /**
29
+ * Request payload for a guarded prompt invocation.
30
+ */
31
+ export type PromptInvocation = {
32
+ policyRef: string;
33
+ policy: PromptPolicy;
34
+ systemContext?: string;
35
+ userData: string;
36
+ messages?: Array<{
37
+ role: 'user' | 'system';
38
+ content: string;
39
+ }>;
40
+ requestId?: string;
41
+ tenantId?: string;
42
+ userId?: string;
43
+ };
44
+ /**
45
+ * Result of a guarded prompt invocation.
46
+ */
47
+ export type PromptInvocationResult<T = unknown> = {
48
+ success: true;
49
+ data: T;
50
+ requestId: string;
51
+ refused: false;
52
+ } | {
53
+ success: false;
54
+ refused: true;
55
+ reason: PromptRefusalReason;
56
+ requestId: string;
57
+ message?: string;
58
+ };
59
+ /**
60
+ * Privacy-safe telemetry event.
61
+ * Default: hashed payloads only; no raw prompt/response.
62
+ */
63
+ export type PromptTelemetryEvent = {
64
+ requestId: string;
65
+ policyRef: string;
66
+ promptId: string;
67
+ promptVersion: string;
68
+ promptHash: string;
69
+ outputHash: string;
70
+ latencyMs: number;
71
+ tokensIn: number;
72
+ tokensOut: number;
73
+ tenantId?: string;
74
+ userId?: string;
75
+ policyHit?: PromptRefusalReason | null;
76
+ toolNames?: string[];
77
+ };
78
+ /**
79
+ * Schema for structured output validation.
80
+ */
81
+ export type OutputSchema<T = unknown> = ZodType<T>;
82
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;CACH,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,GAAG,OAAO,IAAI;IAChD,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;IACR,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,KAAK,CAAC;CAChB,GAAG;IACF,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@bstockwelldev/prompt-guardrails-core",
3
+ "version": "1.0.0",
4
+ "description": "Stateless server-side prompt guardrails: policy, input/output validation, structured invocation, and privacy-safe telemetry",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": ["dist"],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "prepare": "tsc",
19
+ "typecheck": "tsc --noEmit",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/bstockwelldev/prompt-guardrails-core.git"
26
+ },
27
+ "license": "MIT",
28
+ "keywords": ["prompt", "guardrails", "llm", "validation", "injection", "telemetry"],
29
+ "dependencies": {
30
+ "zod": "^3.25.76"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^20.0.0",
34
+ "typescript": ">=5.3",
35
+ "vitest": "^2.0.0"
36
+ },
37
+ "engines": {
38
+ "node": ">=20.0.0"
39
+ }
40
+ }